wotp 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
wotp-1.0.0/.gitignore ADDED
@@ -0,0 +1,80 @@
1
+ # ─── OS & IDEs ─────────────────────────────────────────────────
2
+ .DS_Store
3
+ Thumbs.db
4
+ .idea/
5
+ .vscode/
6
+ *.swp
7
+ *.swo
8
+
9
+ # ─── Go ────────────────────────────────────────────────────────
10
+ bin/
11
+ obj/
12
+ *.exe
13
+ *.exe~
14
+ *.dll
15
+ *.so
16
+ *.dylib
17
+ *.test
18
+ *.out
19
+ vendor/
20
+ # Goreleaser & local builds
21
+ dist/
22
+ /wotp-cli-*
23
+ /wotp-core
24
+ /wotp
25
+
26
+ # ─── Node.js / React (Dashboard & TS SDK) ──────────────────────
27
+ node_modules/
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+ .pnpm-debug.log*
32
+ # Vite output
33
+ core/dashboard/dist/
34
+ # TS SDK output
35
+ sdks/typescript/dist/
36
+
37
+ # ─── Python (Python SDK) ───────────────────────────────────────
38
+ __pycache__/
39
+ *.py[cod]
40
+ *$py.class
41
+ *.so
42
+ .Python
43
+ env/
44
+ build/
45
+ develop-eggs/
46
+ dist/
47
+ downloads/
48
+ eggs/
49
+ .eggs/
50
+ lib/
51
+ lib64/
52
+ parts/
53
+ sdist/
54
+ var/
55
+ wheels/
56
+ *.egg-info/
57
+ .installed.cfg
58
+ *.egg
59
+ venv/
60
+ .venv/
61
+ .pytest_cache/
62
+
63
+ # ─── Environment & Secrets ─────────────────────────────────────
64
+ .env
65
+ .env.*
66
+ !.env.example
67
+ *.pem
68
+
69
+ # ─── Project Specific Data ─────────────────────────────────────
70
+ # SQLite databases
71
+ *.db
72
+ *.sqlite
73
+ *.sqlite3
74
+ *.db-shm
75
+ *.db-wal
76
+ # Local CLI test folders
77
+ .wotp/
78
+ data/
79
+
80
+ inspiration/
wotp-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: wotp
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for Wotp — WhatsApp OTP, self-hosted, one command.
5
+ Project-URL: Homepage, https://github.com/wotp/wotp
6
+ Project-URL: Documentation, https://github.com/wotp/wotp
7
+ Project-URL: Repository, https://github.com/wotp/wotp
8
+ Author: Wotp
9
+ License-Expression: MIT
10
+ Keywords: 2fa,auth,otp,verification,whatsapp,wotp
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: pydantic>=2.0.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # wotp
26
+
27
+ Official Python SDK for **Wotp** — WhatsApp OTP, self-hosted, one command.
28
+
29
+ [![PyPI](https://img.shields.io/pypi/v/wotp)](https://pypi.org/project/wotp/)
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install wotp
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```python
41
+ from wotp import create_client
42
+
43
+ client = create_client("http://localhost:54321", "wotp_anon_xxx")
44
+
45
+ # Send an OTP
46
+ resp = client.send_otp("+212600000000")
47
+ print(f"Token: {resp.token}, expires at: {resp.expires_at}")
48
+
49
+ # Verify the code entered by the user
50
+ result = client.verify_otp(resp.token, "483920")
51
+
52
+ # Send a text message
53
+ text_res = client.send_text("+212600000000", "Hello world")
54
+
55
+ # Send a media message
56
+ media_res = client.send_media("+212600000000", url="https://example.com/image.png")
57
+
58
+ # List chats
59
+ chats = client.get_chats()
60
+
61
+ print(f"Verified: {result.verified}")
62
+ ```
63
+
64
+ ## API Reference
65
+
66
+ ### `create_client(url, api_key, **options)`
67
+
68
+ Creates a new Wotp client instance.
69
+
70
+ | Parameter | Type | Description |
71
+ |-----------|------|-------------|
72
+ | `url` | `str` | Base URL of your Wotp instance |
73
+ | `api_key` | `str` | Your anon or service API key |
74
+ | `max_retries` | `int` | Max retries on transient errors (default: `3`) |
75
+ | `retry_delay` | `float` | Base delay in seconds between retries (default: `0.5`) |
76
+ | `timeout` | `float` | Request timeout in seconds (default: `10.0`) |
77
+
78
+ ### `client.send_otp(phone)`
79
+
80
+ Send an OTP to the given phone number.
81
+
82
+ - **Parameters:** `phone` — E.164 formatted phone number
83
+ - **Returns:** `SendOTPResponse` with `.token` and `.expires_at`
84
+ - **Raises:** `RateLimitError`
85
+
86
+ ### `client.verify_otp(token, code)`
87
+
88
+ Verify an OTP code against a previously issued token.
89
+
90
+ - **Parameters:** `token` — from `send_otp`, `code` — the user-entered code
91
+ - **Returns:** `VerifyOTPResponse` with `.verified`, `.phone`, `.attempts_remaining`
92
+ - **Raises:** `ExpiredTokenError`, `InvalidCodeError`
93
+
94
+ ### `client.health()`
95
+
96
+ Check the health of the Wotp instance.
97
+
98
+ - **Returns:** `HealthResponse` with `.status`, `.phone`, `.uptime_seconds`
99
+
100
+ ## Error Handling
101
+
102
+ The SDK raises typed exceptions for business failures:
103
+
104
+ ```python
105
+ from wotp import create_client, RateLimitError, ExpiredTokenError, InvalidCodeError
106
+
107
+ client = create_client("http://localhost:54321", "wotp_anon_xxx")
108
+
109
+ try:
110
+ result = client.verify_otp(token, code)
111
+ except RateLimitError as e:
112
+ print(f"Rate limited. Retry after {e.retry_after}s")
113
+ except ExpiredTokenError:
114
+ print("Token expired — request a new OTP")
115
+ except InvalidCodeError as e:
116
+ print(f"Wrong code. {e.attempts_remaining} attempts left")
117
+ ```
118
+
119
+ | Exception | When |
120
+ |-----------|------|
121
+ | `RateLimitError` | Phone/IP exceeded rate limit (HTTP 429) |
122
+ | `ExpiredTokenError` | Token has expired (HTTP 410 or `expired_token`) |
123
+ | `InvalidCodeError` | Wrong OTP code (HTTP 400 + `invalid_code`) |
124
+ | `WotpError` | Base class for all SDK errors |
125
+
126
+ ## Context Manager
127
+
128
+ The client can be used as a context manager to ensure proper cleanup:
129
+
130
+ ```python
131
+ with create_client("http://localhost:54321", "wotp_anon_xxx") as client:
132
+ resp = client.send_otp("+212600000000")
133
+ ```
134
+
135
+ ## Auto-Retry
136
+
137
+ Transient errors (502, 503, 504, network timeouts) are automatically retried with exponential backoff. Business errors are **never** retried.
138
+
139
+ ## Requirements
140
+
141
+ - Python ≥ 3.10
142
+ - A running Wotp instance
143
+
144
+ ## License
145
+
146
+ MIT — see [LICENSE](../../LICENSE) for details.
wotp-1.0.0/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # wotp
2
+
3
+ Official Python SDK for **Wotp** — WhatsApp OTP, self-hosted, one command.
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/wotp)](https://pypi.org/project/wotp/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pip install wotp
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```python
17
+ from wotp import create_client
18
+
19
+ client = create_client("http://localhost:54321", "wotp_anon_xxx")
20
+
21
+ # Send an OTP
22
+ resp = client.send_otp("+212600000000")
23
+ print(f"Token: {resp.token}, expires at: {resp.expires_at}")
24
+
25
+ # Verify the code entered by the user
26
+ result = client.verify_otp(resp.token, "483920")
27
+
28
+ # Send a text message
29
+ text_res = client.send_text("+212600000000", "Hello world")
30
+
31
+ # Send a media message
32
+ media_res = client.send_media("+212600000000", url="https://example.com/image.png")
33
+
34
+ # List chats
35
+ chats = client.get_chats()
36
+
37
+ print(f"Verified: {result.verified}")
38
+ ```
39
+
40
+ ## API Reference
41
+
42
+ ### `create_client(url, api_key, **options)`
43
+
44
+ Creates a new Wotp client instance.
45
+
46
+ | Parameter | Type | Description |
47
+ |-----------|------|-------------|
48
+ | `url` | `str` | Base URL of your Wotp instance |
49
+ | `api_key` | `str` | Your anon or service API key |
50
+ | `max_retries` | `int` | Max retries on transient errors (default: `3`) |
51
+ | `retry_delay` | `float` | Base delay in seconds between retries (default: `0.5`) |
52
+ | `timeout` | `float` | Request timeout in seconds (default: `10.0`) |
53
+
54
+ ### `client.send_otp(phone)`
55
+
56
+ Send an OTP to the given phone number.
57
+
58
+ - **Parameters:** `phone` — E.164 formatted phone number
59
+ - **Returns:** `SendOTPResponse` with `.token` and `.expires_at`
60
+ - **Raises:** `RateLimitError`
61
+
62
+ ### `client.verify_otp(token, code)`
63
+
64
+ Verify an OTP code against a previously issued token.
65
+
66
+ - **Parameters:** `token` — from `send_otp`, `code` — the user-entered code
67
+ - **Returns:** `VerifyOTPResponse` with `.verified`, `.phone`, `.attempts_remaining`
68
+ - **Raises:** `ExpiredTokenError`, `InvalidCodeError`
69
+
70
+ ### `client.health()`
71
+
72
+ Check the health of the Wotp instance.
73
+
74
+ - **Returns:** `HealthResponse` with `.status`, `.phone`, `.uptime_seconds`
75
+
76
+ ## Error Handling
77
+
78
+ The SDK raises typed exceptions for business failures:
79
+
80
+ ```python
81
+ from wotp import create_client, RateLimitError, ExpiredTokenError, InvalidCodeError
82
+
83
+ client = create_client("http://localhost:54321", "wotp_anon_xxx")
84
+
85
+ try:
86
+ result = client.verify_otp(token, code)
87
+ except RateLimitError as e:
88
+ print(f"Rate limited. Retry after {e.retry_after}s")
89
+ except ExpiredTokenError:
90
+ print("Token expired — request a new OTP")
91
+ except InvalidCodeError as e:
92
+ print(f"Wrong code. {e.attempts_remaining} attempts left")
93
+ ```
94
+
95
+ | Exception | When |
96
+ |-----------|------|
97
+ | `RateLimitError` | Phone/IP exceeded rate limit (HTTP 429) |
98
+ | `ExpiredTokenError` | Token has expired (HTTP 410 or `expired_token`) |
99
+ | `InvalidCodeError` | Wrong OTP code (HTTP 400 + `invalid_code`) |
100
+ | `WotpError` | Base class for all SDK errors |
101
+
102
+ ## Context Manager
103
+
104
+ The client can be used as a context manager to ensure proper cleanup:
105
+
106
+ ```python
107
+ with create_client("http://localhost:54321", "wotp_anon_xxx") as client:
108
+ resp = client.send_otp("+212600000000")
109
+ ```
110
+
111
+ ## Auto-Retry
112
+
113
+ Transient errors (502, 503, 504, network timeouts) are automatically retried with exponential backoff. Business errors are **never** retried.
114
+
115
+ ## Requirements
116
+
117
+ - Python ≥ 3.10
118
+ - A running Wotp instance
119
+
120
+ ## License
121
+
122
+ MIT — see [LICENSE](../../LICENSE) for details.
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "wotp"
7
+ version = "1.0.0"
8
+ description = "Official Python SDK for Wotp — WhatsApp OTP, self-hosted, one command."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Wotp" },
14
+ ]
15
+ keywords = ["wotp", "otp", "whatsapp", "verification", "2fa", "auth"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Typing :: Typed",
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27.0",
29
+ "pydantic>=2.0.0",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/wotp/wotp"
34
+ Documentation = "https://github.com/wotp/wotp"
35
+ Repository = "https://github.com/wotp/wotp"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["wotp"]