Skip to content

Commit 049e998

Browse files
committed
[client] add new methods
1 parent 0e1481e commit 049e998

7 files changed

Lines changed: 1388 additions & 55 deletions

File tree

README.md

Lines changed: 207 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# 📱 SMS Gateway for Android™ Python API Client
1+
# 📱 SMSGate Python API Client
22

33
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=for-the-badge)](https://github.com/android-sms-gateway/client-py/blob/master/LICENSE)
44
[![PyPI Version](https://img.shields.io/pypi/v/android-sms-gateway.svg?style=for-the-badge)](https://pypi.org/project/android-sms-gateway/)
@@ -26,7 +26,7 @@ Key value propositions:
2626
This client abstracts away the complexities of the underlying HTTP API while providing all the necessary functionality to send and track SMS messages through Android devices.
2727

2828
## 📚 Table of Contents
29-
- [📱 SMS Gateway for Android™ Python API Client](#-sms-gateway-for-android-python-api-client)
29+
- [📱 SMSGate Python API Client](#-smsgate-python-api-client)
3030
- [📖 About The Project](#-about-the-project)
3131
- [📚 Table of Contents](#-table-of-contents)
3232
- [✨ Features](#-features)
@@ -42,12 +42,24 @@ This client abstracts away the complexities of the underlying HTTP API while pro
4242
- [🤖 Client Guide](#-client-guide)
4343
- [Client Configuration](#client-configuration)
4444
- [Available Methods](#available-methods)
45+
- [Message Methods](#message-methods)
46+
- [Webhook Methods](#webhook-methods)
47+
- [Device Methods](#device-methods)
48+
- [Settings Methods](#settings-methods)
49+
- [Log Methods](#log-methods)
50+
- [Health Check Methods](#health-check-methods)
51+
- [Token Methods](#token-methods)
4552
- [Data Structures](#data-structures)
4653
- [Message](#message)
4754
- [MessageState](#messagestate)
4855
- [Webhook](#webhook)
56+
- [Device](#device)
57+
- [DeviceSettings](#devicesettings)
4958
- [TokenRequest](#tokenrequest)
5059
- [TokenResponse](#tokenresponse)
60+
- [HealthResponse](#healthresponse)
61+
- [LogEntry](#logentry)
62+
- [Enums](#enums)
5163
- [🌐 HTTP Clients](#-http-clients)
5264
- [Using Specific Clients](#using-specific-clients)
5365
- [Custom HTTP Client](#custom-http-client)
@@ -75,7 +87,13 @@ This client abstracts away the complexities of the underlying HTTP API while pro
7587
- 💻 **Full Type Hinting**: Fully typed for better development experience
7688
- ⚠️ **Robust Error Handling**: Specific exceptions and clear error messages
7789
- 📈 **Delivery Reports**: Track your message delivery status
78-
- 🔑 **Token Management**: Generate and revoke JWT tokens with custom scopes and TTL
90+
- 🔑 **Token Management**: Generate, refresh, and revoke JWT tokens with custom scopes and TTL
91+
- 📊 **Message Filtering**: List messages with date range, state, and device filtering
92+
- ⚙️ **Settings Management**: Get, update, and patch device settings
93+
- 📝 **Logging**: Retrieve system logs with time range filtering
94+
- 🏥 **Health Checks**: Liveness, readiness, and startup probes
95+
- 📱 **Device Management**: List and remove registered devices
96+
- 📥 **Inbox Export**: Export received messages via webhooks
7997

8098
## ⚙️ Requirements
8199

@@ -150,22 +168,22 @@ message = domain.Message(
150168
def sync_example():
151169
with client.APIClient(login, password) as c:
152170
# Send message
153-
state = c.send(message)
154-
print(f"Message sent with ID: {state.id}")
171+
response = c.send(message)
172+
print(f"Message sent with ID: {response.id}")
155173

156174
# Check status
157-
status = c.get_state(state.id)
175+
status = c.get_state(response.id)
158176
print(f"Status: {status.state}")
159177

160178
# Asynchronous Client
161179
async def async_example():
162180
async with client.AsyncAPIClient(login, password) as c:
163181
# Send message
164-
state = await c.send(message)
165-
print(f"Message sent with ID: {state.id}")
182+
response = await c.send(message)
183+
print(f"Message sent with ID: {response.id}")
166184

167185
# Check status
168-
status = await c.get_state(state.id)
186+
status = await c.get_state(response.id)
169187
print(f"Status: {status.state}")
170188

171189
if __name__ == "__main__":
@@ -194,8 +212,8 @@ message = domain.Message(
194212

195213
# Client with encryption
196214
with client.APIClient(login, password, encryptor=encryptor) as c:
197-
state = c.send(message)
198-
print(f"Encrypted message sent: {state.id}")
215+
response = c.send(message)
216+
print(f"Encrypted message sent: {response.id}")
199217
```
200218

201219
### JWT Authentication Example
@@ -238,8 +256,8 @@ with client.APIClient(login, password) as c:
238256
text="Hello from newly generated JWT token!",
239257
),
240258
)
241-
state = jwt_client.send(message)
242-
print(f"Message sent with new JWT token: {state.id}")
259+
response = jwt_client.send(message)
260+
print(f"Message sent with new JWT token: {response.id}")
243261

244262
# Revoke the token when no longer needed
245263
jwt_client.revoke_token(token_response.id)
@@ -285,42 +303,91 @@ Both clients (`APIClient` and `AsyncAPIClient`) support these parameters:
285303

286304
### Available Methods
287305

288-
| Method | Description | Return Type |
289-
| ---------------------------------------------------- | -------------------- | ---------------------- |
290-
| `send(message: domain.Message)` | Send SMS message | `domain.MessageState` |
291-
| `get_state(id: str)` | Check message status | `domain.MessageState` |
292-
| `create_webhook(webhook: domain.Webhook)` | Create new webhook | `domain.Webhook` |
293-
| `get_webhooks()` | List all webhooks | `List[domain.Webhook]` |
294-
| `delete_webhook(id: str)` | Delete webhook | `None` |
295-
| `generate_token(token_request: domain.TokenRequest)` | Generate JWT token | `domain.TokenResponse` |
296-
| `revoke_token(jti: str)` | Revoke JWT token | `None` |
306+
#### Message Methods
307+
308+
| Method | Description | Return Type |
309+
| ----------------------------------------------------------------------- | ---------------------------------- | --------------------------- |
310+
| `send(message, *, skip_phone_validation=False, device_active_within=0)` | Send SMS message | `domain.MessageState` |
311+
| `get_state(id)` | Get message state by ID | `domain.MessageState` |
312+
| `get_messages(*, filter=None, pagination=None)` | List messages with filtering | `List[domain.MessageState]` |
313+
| `export_inbox(request)` | Export inbox messages via webhooks | `dict` |
314+
315+
#### Webhook Methods
316+
317+
| Method | Description | Return Type |
318+
| ------------------------- | ------------------ | ---------------------- |
319+
| `create_webhook(webhook)` | Create new webhook | `domain.Webhook` |
320+
| `get_webhooks()` | List all webhooks | `List[domain.Webhook]` |
321+
| `delete_webhook(id)` | Delete webhook | `None` |
322+
323+
#### Device Methods
324+
325+
| Method | Description | Return Type |
326+
| ------------------- | --------------------------- | --------------------- |
327+
| `list_devices()` | List all registered devices | `List[domain.Device]` |
328+
| `remove_device(id)` | Remove a device | `None` |
329+
330+
#### Settings Methods
331+
332+
| Method | Description | Return Type |
333+
| --------------------------- | ------------------------- | ----------------------- |
334+
| `get_settings()` | Get device settings | `domain.DeviceSettings` |
335+
| `update_settings(settings)` | Replace settings | `dict` |
336+
| `patch_settings(settings)` | Partially update settings | `dict` |
337+
338+
#### Log Methods
339+
340+
| Method | Description | Return Type |
341+
| ------------------------------- | --------------- | ----------------------- |
342+
| `get_logs(from_=None, to=None)` | Get log entries | `List[domain.LogEntry]` |
343+
344+
#### Health Check Methods
345+
346+
| Method | Description | Return Type |
347+
| ------------------- | --------------- | ----------------------- |
348+
| `health_check()` | Readiness probe | `domain.HealthResponse` |
349+
| `liveness_check()` | Liveness probe | `domain.HealthResponse` |
350+
| `readiness_check()` | Readiness probe | `domain.HealthResponse` |
351+
| `startup_check()` | Startup probe | `domain.HealthResponse` |
352+
353+
#### Token Methods
354+
355+
| Method | Description | Return Type |
356+
| ------------------------------- | -------------------- | ---------------------- |
357+
| `generate_token(token_request)` | Generate JWT token | `domain.TokenResponse` |
358+
| `refresh_token(refresh_token)` | Refresh access token | `domain.TokenResponse` |
359+
| `revoke_token(jti)` | Revoke JWT token | `None` |
297360

298361
### Data Structures
299362

300363
#### Message
301364

302365
```python
303366
class Message:
304-
message: str # Message text
305-
phone_numbers: List[str] # List of phone numbers
367+
phone_numbers: List[str] # List of phone numbers (required)
368+
text_message: Optional[TextMessage] = None # Text message
369+
data_message: Optional[DataMessage] = None # Data message
370+
priority: Optional[MessagePriority] = None # Message priority
371+
sim_number: Optional[int] = None # SIM card number (1-3)
306372
with_delivery_report: bool = True # Delivery report
307373
is_encrypted: bool = False # Whether message is encrypted
308-
309-
# Optional fields
310-
id: Optional[str] = None # Message ID
311-
ttl: Optional[int] = None # Time-to-live in seconds
312-
sim_number: Optional[int] = None # SIM number
374+
ttl: Optional[int] = None # Time-to-live in seconds
375+
valid_until: Optional[datetime] = None # Valid until timestamp
376+
id: Optional[str] = None # Message ID
377+
device_id: Optional[str] = None # Device ID for explicit selection
313378
```
314379

315380
#### MessageState
316381

317382
```python
318383
class MessageState:
319-
id: str # Unique message ID
320-
state: ProcessState # Current state (SENT, DELIVERED, etc.)
321-
recipients: List[RecipientState] # Per-recipient status
322-
is_hashed: bool # Whether message was hashed
323-
is_encrypted: bool # Whether message was encrypted
384+
id: str # Unique message ID
385+
state: ProcessState # Current processing state
386+
recipients: List[RecipientState] # Per-recipient status
387+
is_hashed: bool = False # Whether phone numbers are hashed
388+
is_encrypted: bool = False # Whether message was encrypted
389+
device_id: Optional[str] = None # Device ID (optional for backward compatibility)
390+
states: Optional[Dict[str, str]] = None # History of state changes
324391
```
325392

326393
#### Webhook
@@ -330,24 +397,125 @@ class Webhook:
330397
id: Optional[str] # Webhook ID
331398
url: str # Callback URL
332399
event: WebhookEvent # Event type
400+
device_id: Optional[str] = None # Associated device ID
401+
```
402+
403+
#### Device
404+
405+
```python
406+
class Device:
407+
id: str # Unique device identifier
408+
name: str # Device name
409+
created_at: Optional[datetime] = None # Creation timestamp
410+
updated_at: Optional[datetime] = None # Last update timestamp
411+
deleted_at: Optional[datetime] = None # Deletion timestamp
412+
last_seen: Optional[datetime] = None # Last seen timestamp
413+
```
414+
415+
#### DeviceSettings
416+
417+
```python
418+
class DeviceSettings:
419+
gateway: Optional[SettingsGateway] = None # Gateway settings
420+
encryption: Optional[SettingsEncryption] = None # Encryption settings
421+
messages: Optional[SettingsMessages] = None # Message handling settings
422+
logs: Optional[SettingsLogs] = None # Logging settings
423+
ping: Optional[SettingsPing] = None # Ping settings
424+
webhooks: Optional[SettingsWebhooks] = None # Webhook settings
333425
```
334426

335427
#### TokenRequest
336428

337429
```python
338430
class TokenRequest:
339-
scopes: List[str] # List of scopes for the token
340-
ttl: Optional[int] = None # Time to live for the token in seconds
431+
scopes: List[str] # List of scopes for the token (required)
432+
ttl: Optional[int] = None # Time to live in seconds
341433
```
342434

343435
#### TokenResponse
344436

345437
```python
346438
class TokenResponse:
347439
access_token: str # The JWT access token
348-
token_type: str # The type of the token (e.g., 'Bearer')
349-
id: str # The unique identifier of the token (jti)
350-
expires_at: str # The expiration time of the token in ISO format
440+
token_type: str # Token type (e.g., 'Bearer')
441+
id: str # Unique token identifier (jti)
442+
expires_at: str # Expiration time in ISO format
443+
refresh_token: Optional[str] = None # Refresh token
444+
```
445+
446+
#### HealthResponse
447+
448+
```python
449+
class HealthResponse:
450+
status: HealthStatus # Overall health status
451+
version: Optional[str] = None # Application version
452+
release_id: Optional[int] = None # Release ID
453+
checks: Optional[Dict[str, HealthCheck]] = None # Individual health checks
454+
```
455+
456+
#### LogEntry
457+
458+
```python
459+
class LogEntry:
460+
id: int # Unique log entry ID
461+
created_at: datetime # Creation timestamp
462+
message: str # Log message
463+
priority: LogEntryPriority # Priority level (DEBUG, INFO, WARN, ERROR)
464+
module: Optional[str] = None # Source module
465+
context: Optional[Dict] = None # Additional context
466+
```
467+
468+
#### Enums
469+
470+
```python
471+
class ProcessState(enum.Enum):
472+
Pending = "Pending"
473+
Processed = "Processed"
474+
Sent = "Sent"
475+
Delivered = "Delivered"
476+
Failed = "Failed"
477+
478+
class WebhookEvent(enum.Enum):
479+
SMS_RECEIVED = "sms:received"
480+
SMS_DATA_RECEIVED = "sms:data-received"
481+
SMS_SENT = "sms:sent"
482+
SMS_DELIVERED = "sms:delivered"
483+
SMS_FAILED = "sms:failed"
484+
SYSTEM_PING = "system:ping"
485+
MMS_RECEIVED = "mms:received"
486+
MMS_DOWNLOADED = "mms:downloaded"
487+
488+
class MessagePriority(enum.IntEnum):
489+
MINIMUM = -128
490+
DEFAULT = 0
491+
BYPASS_THRESHOLD = 100
492+
MAXIMUM = 127
493+
494+
class LimitPeriod(enum.Enum):
495+
DISABLED = "Disabled"
496+
PER_MINUTE = "PerMinute"
497+
PER_HOUR = "PerHour"
498+
PER_DAY = "PerDay"
499+
500+
class SimSelectionMode(enum.Enum):
501+
OS_DEFAULT = "OSDefault"
502+
ROUND_ROBIN = "RoundRobin"
503+
RANDOM = "Random"
504+
505+
class MessagesProcessingOrder(enum.Enum):
506+
LIFO = "LIFO"
507+
FIFO = "FIFO"
508+
509+
class HealthStatus(enum.Enum):
510+
PASS = "pass"
511+
WARN = "warn"
512+
FAIL = "fail"
513+
514+
class LogEntryPriority(enum.Enum):
515+
DEBUG = "DEBUG"
516+
INFO = "INFO"
517+
WARN = "WARN"
518+
ERROR = "ERROR"
351519
```
352520

353521
For more details, see [`domain.py`](./android_sms_gateway/domain.py).

0 commit comments

Comments
 (0)