jambonz-python-sdk 0.2.0__py3-none-any.whl
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.
- jambonz_python_sdk-0.2.0.dist-info/METADATA +179 -0
- jambonz_python_sdk-0.2.0.dist-info/RECORD +119 -0
- jambonz_python_sdk-0.2.0.dist-info/WHEEL +4 -0
- jambonz_sdk/__init__.py +52 -0
- jambonz_sdk/_signature.py +73 -0
- jambonz_sdk/client/__init__.py +15 -0
- jambonz_sdk/client/api.py +241 -0
- jambonz_sdk/schema/callbacks/amd.schema.json +50 -0
- jambonz_sdk/schema/callbacks/base.schema.json +29 -0
- jambonz_sdk/schema/callbacks/call-status.schema.json +22 -0
- jambonz_sdk/schema/callbacks/conference-status.schema.json +24 -0
- jambonz_sdk/schema/callbacks/conference-wait.schema.json +11 -0
- jambonz_sdk/schema/callbacks/conference.schema.json +11 -0
- jambonz_sdk/schema/callbacks/dequeue.schema.json +19 -0
- jambonz_sdk/schema/callbacks/dial-dtmf.schema.json +18 -0
- jambonz_sdk/schema/callbacks/dial-hold.schema.json +22 -0
- jambonz_sdk/schema/callbacks/dial-refer.schema.json +28 -0
- jambonz_sdk/schema/callbacks/dial.schema.json +31 -0
- jambonz_sdk/schema/callbacks/enqueue-wait.schema.json +17 -0
- jambonz_sdk/schema/callbacks/enqueue.schema.json +27 -0
- jambonz_sdk/schema/callbacks/gather-partial.schema.json +54 -0
- jambonz_sdk/schema/callbacks/gather.schema.json +60 -0
- jambonz_sdk/schema/callbacks/listen.schema.json +21 -0
- jambonz_sdk/schema/callbacks/llm.schema.json +30 -0
- jambonz_sdk/schema/callbacks/message.schema.json +35 -0
- jambonz_sdk/schema/callbacks/pipeline-turn.schema.json +109 -0
- jambonz_sdk/schema/callbacks/play.schema.json +36 -0
- jambonz_sdk/schema/callbacks/session-new.schema.json +143 -0
- jambonz_sdk/schema/callbacks/session-reconnect.schema.json +9 -0
- jambonz_sdk/schema/callbacks/session-redirect.schema.json +38 -0
- jambonz_sdk/schema/callbacks/sip-refer-event.schema.json +20 -0
- jambonz_sdk/schema/callbacks/sip-refer.schema.json +22 -0
- jambonz_sdk/schema/callbacks/sip-request.schema.json +27 -0
- jambonz_sdk/schema/callbacks/transcribe-translation.schema.json +24 -0
- jambonz_sdk/schema/callbacks/transcribe.schema.json +46 -0
- jambonz_sdk/schema/callbacks/tts-streaming-event.schema.json +77 -0
- jambonz_sdk/schema/callbacks/verb-status.schema.json +57 -0
- jambonz_sdk/schema/components/actionHook.schema.json +36 -0
- jambonz_sdk/schema/components/actionHookDelayAction.schema.json +37 -0
- jambonz_sdk/schema/components/amd.schema.json +68 -0
- jambonz_sdk/schema/components/auth.schema.json +18 -0
- jambonz_sdk/schema/components/bidirectionalAudio.schema.json +22 -0
- jambonz_sdk/schema/components/fillerNoise.schema.json +25 -0
- jambonz_sdk/schema/components/llm-base.schema.json +94 -0
- jambonz_sdk/schema/components/recognizer-assemblyAiOptions.schema.json +66 -0
- jambonz_sdk/schema/components/recognizer-awsOptions.schema.json +52 -0
- jambonz_sdk/schema/components/recognizer-azureOptions.schema.json +32 -0
- jambonz_sdk/schema/components/recognizer-cobaltOptions.schema.json +34 -0
- jambonz_sdk/schema/components/recognizer-customOptions.schema.json +27 -0
- jambonz_sdk/schema/components/recognizer-deepgramOptions.schema.json +147 -0
- jambonz_sdk/schema/components/recognizer-elevenlabsOptions.schema.json +39 -0
- jambonz_sdk/schema/components/recognizer-gladiaOptions.schema.json +8 -0
- jambonz_sdk/schema/components/recognizer-googleOptions.schema.json +35 -0
- jambonz_sdk/schema/components/recognizer-houndifyOptions.schema.json +53 -0
- jambonz_sdk/schema/components/recognizer-ibmOptions.schema.json +54 -0
- jambonz_sdk/schema/components/recognizer-nuanceOptions.schema.json +150 -0
- jambonz_sdk/schema/components/recognizer-nvidiaOptions.schema.json +39 -0
- jambonz_sdk/schema/components/recognizer-openaiOptions.schema.json +59 -0
- jambonz_sdk/schema/components/recognizer-sonioxOptions.schema.json +46 -0
- jambonz_sdk/schema/components/recognizer-speechmaticsOptions.schema.json +100 -0
- jambonz_sdk/schema/components/recognizer-verbioOptions.schema.json +46 -0
- jambonz_sdk/schema/components/recognizer.schema.json +216 -0
- jambonz_sdk/schema/components/synthesizer.schema.json +82 -0
- jambonz_sdk/schema/components/target.schema.json +105 -0
- jambonz_sdk/schema/components/vad.schema.json +48 -0
- jambonz_sdk/schema/jambonz-app.schema.json +113 -0
- jambonz_sdk/schema/verbs/alert.schema.json +34 -0
- jambonz_sdk/schema/verbs/answer.schema.json +22 -0
- jambonz_sdk/schema/verbs/conference.schema.json +107 -0
- jambonz_sdk/schema/verbs/config.schema.json +221 -0
- jambonz_sdk/schema/verbs/deepgram_s2s.schema.json +81 -0
- jambonz_sdk/schema/verbs/dequeue.schema.json +51 -0
- jambonz_sdk/schema/verbs/dial.schema.json +200 -0
- jambonz_sdk/schema/verbs/dialogflow.schema.json +148 -0
- jambonz_sdk/schema/verbs/dtmf.schema.json +49 -0
- jambonz_sdk/schema/verbs/dub.schema.json +103 -0
- jambonz_sdk/schema/verbs/elevenlabs_s2s.schema.json +81 -0
- jambonz_sdk/schema/verbs/enqueue.schema.json +53 -0
- jambonz_sdk/schema/verbs/gather.schema.json +190 -0
- jambonz_sdk/schema/verbs/google_s2s.schema.json +42 -0
- jambonz_sdk/schema/verbs/hangup.schema.json +36 -0
- jambonz_sdk/schema/verbs/leave.schema.json +22 -0
- jambonz_sdk/schema/verbs/listen.schema.json +127 -0
- jambonz_sdk/schema/verbs/llm.schema.json +44 -0
- jambonz_sdk/schema/verbs/message.schema.json +82 -0
- jambonz_sdk/schema/verbs/openai_s2s.schema.json +42 -0
- jambonz_sdk/schema/verbs/pause.schema.json +36 -0
- jambonz_sdk/schema/verbs/pipeline.schema.json +240 -0
- jambonz_sdk/schema/verbs/play.schema.json +96 -0
- jambonz_sdk/schema/verbs/redirect.schema.json +34 -0
- jambonz_sdk/schema/verbs/rest_dial.schema.json +113 -0
- jambonz_sdk/schema/verbs/s2s.schema.json +39 -0
- jambonz_sdk/schema/verbs/say.schema.json +107 -0
- jambonz_sdk/schema/verbs/sip-decline.schema.json +58 -0
- jambonz_sdk/schema/verbs/sip-refer.schema.json +58 -0
- jambonz_sdk/schema/verbs/sip-request.schema.json +54 -0
- jambonz_sdk/schema/verbs/stream.schema.json +103 -0
- jambonz_sdk/schema/verbs/tag.schema.json +41 -0
- jambonz_sdk/schema/verbs/transcribe.schema.json +57 -0
- jambonz_sdk/schema/verbs/ultravox_s2s.schema.json +41 -0
- jambonz_sdk/types/__init__.py +139 -0
- jambonz_sdk/types/components.py +250 -0
- jambonz_sdk/types/rest.py +59 -0
- jambonz_sdk/types/session.py +55 -0
- jambonz_sdk/types/verbs.py +572 -0
- jambonz_sdk/validator.py +107 -0
- jambonz_sdk/verb_builder.py +316 -0
- jambonz_sdk/verb_builder.pyi +1133 -0
- jambonz_sdk/verb_registry.py +102 -0
- jambonz_sdk/webhook/__init__.py +10 -0
- jambonz_sdk/webhook/middleware.py +63 -0
- jambonz_sdk/webhook/response.py +43 -0
- jambonz_sdk/websocket/__init__.py +15 -0
- jambonz_sdk/websocket/audio_client.py +11 -0
- jambonz_sdk/websocket/audio_stream.py +151 -0
- jambonz_sdk/websocket/client.py +165 -0
- jambonz_sdk/websocket/endpoint.py +193 -0
- jambonz_sdk/websocket/router.py +87 -0
- jambonz_sdk/websocket/session.py +259 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: jambonz-python-sdk
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python SDK for jambonz CPaaS platform
|
|
5
|
+
Project-URL: Homepage, https://github.com/jambonz/jambonz-python-sdk
|
|
6
|
+
Project-URL: Repository, https://github.com/jambonz/jambonz-python-sdk
|
|
7
|
+
Project-URL: Issues, https://github.com/jambonz/jambonz-python-sdk/issues
|
|
8
|
+
Project-URL: Documentation, https://jambonz.org
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Keywords: cpaas,jambonz,sip,telephony,voip,websocket
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Framework :: AsyncIO
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Communications :: Telephony
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: aiohttp>=3.9
|
|
23
|
+
Requires-Dist: jsonschema>=4.20
|
|
24
|
+
Requires-Dist: referencing>=0.31
|
|
25
|
+
Requires-Dist: typing-extensions>=4.0; python_version < '3.11'
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: aioresponses>=0.7; extra == 'dev'
|
|
28
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# jambonz Python SDK
|
|
36
|
+
|
|
37
|
+
Python SDK for the [jambonz](https://jambonz.org) CPaaS platform.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install jambonz-python-sdk
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### Webhook (HTTP)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from aiohttp import web
|
|
51
|
+
from jambonz_sdk.webhook import WebhookResponse
|
|
52
|
+
|
|
53
|
+
async def handle_incoming(request: web.Request) -> web.Response:
|
|
54
|
+
jambonz = WebhookResponse()
|
|
55
|
+
jambonz.say(text="Hello!").gather(
|
|
56
|
+
input=["speech"],
|
|
57
|
+
actionHook="/handle-input",
|
|
58
|
+
timeout=10,
|
|
59
|
+
say={"text": "Please say something."},
|
|
60
|
+
).hangup()
|
|
61
|
+
return web.json_response(jambonz.to_json())
|
|
62
|
+
|
|
63
|
+
app = web.Application()
|
|
64
|
+
app.router.add_post("/incoming", handle_incoming)
|
|
65
|
+
web.run_app(app, port=3000)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### WebSocket
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import asyncio
|
|
72
|
+
from jambonz_sdk.websocket import create_endpoint
|
|
73
|
+
|
|
74
|
+
async def main():
|
|
75
|
+
make_service, runner = await create_endpoint(port=3000)
|
|
76
|
+
svc = make_service(path="/")
|
|
77
|
+
|
|
78
|
+
async def handle_session(session):
|
|
79
|
+
session.say(text="Hello!").hangup()
|
|
80
|
+
await session.send()
|
|
81
|
+
|
|
82
|
+
svc.on("session:new", handle_session)
|
|
83
|
+
await asyncio.Future()
|
|
84
|
+
|
|
85
|
+
asyncio.run(main())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### REST Client
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from jambonz_sdk.client import JambonzClient
|
|
92
|
+
|
|
93
|
+
async with JambonzClient(
|
|
94
|
+
base_url="https://api.jambonz.us",
|
|
95
|
+
account_sid="your-account-sid",
|
|
96
|
+
api_key="your-api-key",
|
|
97
|
+
) as client:
|
|
98
|
+
call_sid = await client.calls.create({
|
|
99
|
+
"from": "+15085551212",
|
|
100
|
+
"to": {"type": "phone", "number": "+15085551213"},
|
|
101
|
+
"call_hook": "/incoming",
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## How It Works
|
|
106
|
+
|
|
107
|
+
### Spec-driven verb generation
|
|
108
|
+
|
|
109
|
+
The SDK does **not** hardcode verb method signatures. Instead, verb methods (`.say()`, `.gather()`, `.dial()`, `.pipeline()`, etc.) are **auto-generated at import time** from [JSON Schema](https://github.com/jambonz/schema) files — the same schemas used by the Node.js SDK and the jambonz server.
|
|
110
|
+
|
|
111
|
+
**What this means:**
|
|
112
|
+
|
|
113
|
+
- When the schema adds a new property to a verb, the SDK picks it up automatically — no code change needed
|
|
114
|
+
- Every method has **real typed parameters** (not `**kwargs: Any`) so IDEs show autocomplete and type hints
|
|
115
|
+
- Verb synonyms (`stream` ↔ `listen`, `openai_s2s` → `llm` with `vendor: "openai"`) are handled by the registry
|
|
116
|
+
|
|
117
|
+
### Updating the schema
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Download the pinned version from @jambonz/schema:
|
|
121
|
+
python scripts/sync_schema.py
|
|
122
|
+
|
|
123
|
+
# Or copy from a local clone:
|
|
124
|
+
python scripts/sync_schema.py --local /path/to/schema
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If a **new verb** was added (not just new properties), add one line to `verb_registry.py`:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
VerbDef("new_verb", "new_verb", doc="Description.")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Features
|
|
134
|
+
|
|
135
|
+
- **All 31 jambonz verbs**: say, play, gather, dial, conference, enqueue/dequeue, hangup, pause, redirect, config, tag, dtmf, dub, message, alert, answer, leave, listen/stream, transcribe, openai_s2s, google_s2s, deepgram_s2s, elevenlabs_s2s, ultravox_s2s, s2s, llm, dialogflow, pipeline, sip_decline, sip_request, sip_refer
|
|
136
|
+
- **Fluent chainable API**: `.say(...).gather(...).hangup()`
|
|
137
|
+
- **Webhook transport**: `WebhookResponse` for HTTP apps (works with aiohttp, FastAPI, Flask, etc.)
|
|
138
|
+
- **WebSocket transport**: `create_endpoint` with `Session`, event handling, `send()`/`reply()`
|
|
139
|
+
- **REST client**: `JambonzClient` with calls, conferences, queues, mid-call control
|
|
140
|
+
- **Audio streaming**: Bidirectional audio via `AudioStream`
|
|
141
|
+
- **Mid-call control**: inject commands (mute, whisper, record, DTMF, tag)
|
|
142
|
+
- **TTS token streaming**: `send_tts_tokens()` / `flush_tts_tokens()`
|
|
143
|
+
- **Pipeline updates**: `update_pipeline()` for mid-conversation LLM changes
|
|
144
|
+
- **Signature verification**: HMAC-SHA256 webhook signature validation
|
|
145
|
+
- **Env vars**: Portal discovery via OPTIONS + runtime reading
|
|
146
|
+
|
|
147
|
+
## Examples
|
|
148
|
+
|
|
149
|
+
See the [`examples/`](examples/) directory:
|
|
150
|
+
|
|
151
|
+
| Example | Webhook | WebSocket | Description |
|
|
152
|
+
|---------|---------|-----------|-------------|
|
|
153
|
+
| hello-world | [webhook](examples/hello-world/webhook_app.py) | [websocket](examples/hello-world/websocket_app.py) | Minimal greeting |
|
|
154
|
+
| echo | [webhook](examples/echo/webhook_app.py) | [websocket](examples/echo/websocket_app.py) | Speech echo with gather |
|
|
155
|
+
| ivr-menu | [webhook](examples/ivr-menu/webhook_app.py) | — | IVR menu with speech + DTMF |
|
|
156
|
+
| voice-agent | [webhook](examples/voice-agent/webhook_app.py) | [websocket](examples/voice-agent/websocket_app.py) | LLM pipeline with tool calls |
|
|
157
|
+
| dial | [webhook](examples/dial/webhook_app.py) | — | Outbound dial with fallback |
|
|
158
|
+
| listen-record | [webhook](examples/listen-record/webhook_app.py) | [websocket](examples/listen-record/websocket_app.py) | Audio recording |
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Create venv and install
|
|
164
|
+
python3 -m venv .venv
|
|
165
|
+
source .venv/bin/activate
|
|
166
|
+
pip install -e ".[dev]"
|
|
167
|
+
|
|
168
|
+
# Run tests
|
|
169
|
+
pytest tests/unit/ # Fast unit tests (253)
|
|
170
|
+
pytest tests/integration/ # Real server tests (26)
|
|
171
|
+
pytest # All 279 tests
|
|
172
|
+
|
|
173
|
+
# Sync schema from upstream
|
|
174
|
+
python scripts/sync_schema.py
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
jambonz_sdk/__init__.py,sha256=FhooW-LiVUck04Iz_lEY0_LCxfsZo1TPpafaZuKoVQ8,1391
|
|
2
|
+
jambonz_sdk/_signature.py,sha256=3sy95S310ALrTX2_2w3xH5KLBPKYacy08dpYOxu39i8,2007
|
|
3
|
+
jambonz_sdk/validator.py,sha256=A5nXjeF8BguHwpzmHpkjch4Pw__I4DOVp9qmwfgk7F0,3770
|
|
4
|
+
jambonz_sdk/verb_builder.py,sha256=xI1MWPBB0S0PshCJTeRqmSR7FYKdH5QQVCc1IltuCG8,10899
|
|
5
|
+
jambonz_sdk/verb_builder.pyi,sha256=4fgGI-FbFkrE4yyKkCHn7U0KSBJ0HM5kF86UyobGyps,30730
|
|
6
|
+
jambonz_sdk/verb_registry.py,sha256=QNfFpUW_7mcS3pf_35oSHEAfwF7FVBCcpD3QObxki_s,4953
|
|
7
|
+
jambonz_sdk/client/__init__.py,sha256=0EpEk8feWsFOw54cqpe7aMF7ZrHm4BGnTA9Qtg0Id6w,273
|
|
8
|
+
jambonz_sdk/client/api.py,sha256=aN-nQ6BqEiuLKe_jbIu0JjVMSZe2ZPlFYvsJg8vehZI,7442
|
|
9
|
+
jambonz_sdk/schema/jambonz-app.schema.json,sha256=CaOPh8VIlNzwJmBe33Hrki46Efz5_wrEpSYwoCClDQE,4332
|
|
10
|
+
jambonz_sdk/schema/callbacks/amd.schema.json,sha256=2XvGFxiTuQ2kYY0LernYqmTjVEftfx3sek4Sjq5vSnA,1953
|
|
11
|
+
jambonz_sdk/schema/callbacks/base.schema.json,sha256=G0l-doDap-xZypHXZC3ectVK36Z6SHs_iXj5mKxYWYw,1958
|
|
12
|
+
jambonz_sdk/schema/callbacks/call-status.schema.json,sha256=PtPWkRygCdYsP60096stOXrwEbiqvPV9YGvEzpx2XeM,1127
|
|
13
|
+
jambonz_sdk/schema/callbacks/conference-status.schema.json,sha256=YZ-kpaSZMjk1qYZ-CS13NxBNJuJ88i1xElm9s8Dz6KM,1194
|
|
14
|
+
jambonz_sdk/schema/callbacks/conference-wait.schema.json,sha256=IMEBBxFxQUgHf42i9hp2j0an-j24U4D_EJ1eQ1DNJwk,477
|
|
15
|
+
jambonz_sdk/schema/callbacks/conference.schema.json,sha256=mOdI63zITfGRDT-j_bvwKSTgi8AQ2zdf3Fc7YXEzaiY,416
|
|
16
|
+
jambonz_sdk/schema/callbacks/dequeue.schema.json,sha256=s65QvBPCZZ9KeOVlJWJUjZLGIgVnNA4f6p_UwgYwOx4,695
|
|
17
|
+
jambonz_sdk/schema/callbacks/dial-dtmf.schema.json,sha256=mfglBf1cGLz8hFdM7N-O74lxIab08akLku_d680iysM,570
|
|
18
|
+
jambonz_sdk/schema/callbacks/dial-hold.schema.json,sha256=KNUZpiTNLm_XuZI-p7fy1oym9_BcsZ_DrBB1V-Ikgow,828
|
|
19
|
+
jambonz_sdk/schema/callbacks/dial-refer.schema.json,sha256=m__lzLCBzOWLnzyX1Lxuvz3YuAQ2ARxFKCtAfDprOCg,1538
|
|
20
|
+
jambonz_sdk/schema/callbacks/dial.schema.json,sha256=y_3xmAiAMrpG2cadOGqdWdCyw_aWggpF7HLeWBBpObE,1110
|
|
21
|
+
jambonz_sdk/schema/callbacks/enqueue-wait.schema.json,sha256=Gl_BdbW3VpKKF2iRmzT8dgdZUUmqMxCrf2Mp8d2aOZg,1207
|
|
22
|
+
jambonz_sdk/schema/callbacks/enqueue.schema.json,sha256=uGDOHoLZNnfuFb0Dx27YD7GK5ky4iWvlPSps_u5_Sv4,1129
|
|
23
|
+
jambonz_sdk/schema/callbacks/gather-partial.schema.json,sha256=TNmfDqBmWFLJYPTJBS8wf1eoVQ_6bLB4A6jbdUeJDAY,3377
|
|
24
|
+
jambonz_sdk/schema/callbacks/gather.schema.json,sha256=EKApuYTHV_sBcrpGnpR4y5GvYotrJm5M4BIvIUsMZs4,2601
|
|
25
|
+
jambonz_sdk/schema/callbacks/listen.schema.json,sha256=D8_J7MDBhNwEn3nwRHWXkZIsHb0ap2vY2ehfOAI4Vio,686
|
|
26
|
+
jambonz_sdk/schema/callbacks/llm.schema.json,sha256=anXe9QD0X_8pSo_NAj_TJEfKpPNdAfFJQTUOI-Y3ZL4,976
|
|
27
|
+
jambonz_sdk/schema/callbacks/message.schema.json,sha256=t2nO4Gb1bXi9JtA4NwVeFudOFzbyEbnOrGDCFhRxM44,1245
|
|
28
|
+
jambonz_sdk/schema/callbacks/pipeline-turn.schema.json,sha256=1OBaA255zj3Ug0tqtfoWCVNsNcRSinKPDcSNEiBNQ04,4514
|
|
29
|
+
jambonz_sdk/schema/callbacks/play.schema.json,sha256=XpyFUlE1ywhfNmHu-q_KrvQl4jwJqxHQBCIPT9eCrGs,1253
|
|
30
|
+
jambonz_sdk/schema/callbacks/session-new.schema.json,sha256=ENqyXSu6lKb6uOE_xup3xctjjKjKV-lvWRpw1yfnj50,5429
|
|
31
|
+
jambonz_sdk/schema/callbacks/session-reconnect.schema.json,sha256=dMyK4dkahnXVCPg5hAQtsZxb3E8gXKRJ8dkROYMPC-4,538
|
|
32
|
+
jambonz_sdk/schema/callbacks/session-redirect.schema.json,sha256=Xvz7i7R8YjX_J0Zkv_Ovy9KHJ0kcrETRTMgDJRpvcvs,1398
|
|
33
|
+
jambonz_sdk/schema/callbacks/sip-refer-event.schema.json,sha256=rs4AkEVm_zi1SyyCIv94l3uDLwSlZnD_pp-ejmj56z0,751
|
|
34
|
+
jambonz_sdk/schema/callbacks/sip-refer.schema.json,sha256=oGa7Xg8f8aP0gaRfpM0MrlNIuU203ehP9dlWQ5xLkn0,887
|
|
35
|
+
jambonz_sdk/schema/callbacks/sip-request.schema.json,sha256=e0PWYRUwJR-TWYFU7WeI0E7DgfHDRZJTH-gbb_CLAhw,858
|
|
36
|
+
jambonz_sdk/schema/callbacks/transcribe-translation.schema.json,sha256=eRn6eqDuADy0NrcbKX6YmlSS6dVJpR8J0_mj4Ef4hQE,891
|
|
37
|
+
jambonz_sdk/schema/callbacks/transcribe.schema.json,sha256=8-8t7MIpEtpM0ZkdNIZeh820N8jFVAaCFgv-fs41Mmk,2130
|
|
38
|
+
jambonz_sdk/schema/callbacks/tts-streaming-event.schema.json,sha256=yAY-RIoXWm2NhDxuX8JB3OPEktxlBoRAjVjdFN4WmTM,2570
|
|
39
|
+
jambonz_sdk/schema/callbacks/verb-status.schema.json,sha256=PwetY3q0WK8u6rKc3G3ozbDG4Cb6_P0w3HbitjSTg_w,2039
|
|
40
|
+
jambonz_sdk/schema/components/actionHook.schema.json,sha256=cteHhGPzvNfGNJVKWkwdkxbFT6Ph2xDC84_6TwFN1kM,1796
|
|
41
|
+
jambonz_sdk/schema/components/actionHookDelayAction.schema.json,sha256=w3gSk0aUDWWJ8XDMxDl55BYWOmtUV8nP3XRV2Ud9m2o,1722
|
|
42
|
+
jambonz_sdk/schema/components/amd.schema.json,sha256=-WjQJMPqIKbw-za9_BkcwCfYPoQ2nB7LZ1JlSeNDfvc,2863
|
|
43
|
+
jambonz_sdk/schema/components/auth.schema.json,sha256=oqTJ4oKUINFF2kHRARmITSI5C49dTICSVqdizIrv7ek,578
|
|
44
|
+
jambonz_sdk/schema/components/bidirectionalAudio.schema.json,sha256=o9-p_I6ZwcK5ckUpTE7U68yN1tiW3nJSSMvKxu4bf7o,861
|
|
45
|
+
jambonz_sdk/schema/components/fillerNoise.schema.json,sha256=KuNzxDDKgKnlVBiqrJjSyM83wpCEC3Pu8swDYjrR9jE,1054
|
|
46
|
+
jambonz_sdk/schema/components/llm-base.schema.json,sha256=yC5LSVNTbjM_7FF-Jit65J5zF3pa_5ILkwim-zJXlZY,3436
|
|
47
|
+
jambonz_sdk/schema/components/recognizer-assemblyAiOptions.schema.json,sha256=JfjDNUoUOSzX5WD4cKXAAJVrQ-Pv1g29dMzdAwamO7k,2119
|
|
48
|
+
jambonz_sdk/schema/components/recognizer-awsOptions.schema.json,sha256=Z7adtaaVgHjjz3lx6gXghwxZXHQwu36HDADu9tMhS-I,1660
|
|
49
|
+
jambonz_sdk/schema/components/recognizer-azureOptions.schema.json,sha256=r8WNOEuPyan9kVCaRLJ8ycxOwzgQ3s4Kcsb8fd96kJk,1144
|
|
50
|
+
jambonz_sdk/schema/components/recognizer-cobaltOptions.schema.json,sha256=rLbrKh3Cr_LRy8fAPUOpEg7i2dHxtZStqwoumsdeo8I,1031
|
|
51
|
+
jambonz_sdk/schema/components/recognizer-customOptions.schema.json,sha256=1mLPULdn9zGouockiymNoaZwcBtrtG8BBL08rHHdtJY,864
|
|
52
|
+
jambonz_sdk/schema/components/recognizer-deepgramOptions.schema.json,sha256=JygJcdKOXpBDp6nPCq4H8H8pdlSGtC9gzUhuVuClMy8,4385
|
|
53
|
+
jambonz_sdk/schema/components/recognizer-elevenlabsOptions.schema.json,sha256=JriyGgBWSKaStxAJB4LIcFYnWZE-6Diy3XPncWZgmRY,1333
|
|
54
|
+
jambonz_sdk/schema/components/recognizer-gladiaOptions.schema.json,sha256=6Sk_xWl1tB5qTAptKSYPjZJyGG0jK-A0QlmswSSo9YQ,382
|
|
55
|
+
jambonz_sdk/schema/components/recognizer-googleOptions.schema.json,sha256=qIygKgsRnZjW9oZ5i1vA2nSrfEwGk9Wvrl4bJ3mrprk,1158
|
|
56
|
+
jambonz_sdk/schema/components/recognizer-houndifyOptions.schema.json,sha256=EOTFZZTvRZlgr42mHWtn8_c9st0Vw_azYbXwMQbM8YM,3598
|
|
57
|
+
jambonz_sdk/schema/components/recognizer-ibmOptions.schema.json,sha256=0lLxVUYA9735PMi7ZRgjVO4EvoERh54vd9AyK-GtEt0,1555
|
|
58
|
+
jambonz_sdk/schema/components/recognizer-nuanceOptions.schema.json,sha256=PSbtOPUy-FryOY5O0HA03ZSAUAF1mVoS-8RXF2NDaqY,5077
|
|
59
|
+
jambonz_sdk/schema/components/recognizer-nvidiaOptions.schema.json,sha256=AAvwTy5iSrMEw-qoCFmxQPQ_tX4ewk88R4ncphDbDgE,1182
|
|
60
|
+
jambonz_sdk/schema/components/recognizer-openaiOptions.schema.json,sha256=L9H8_0hm5AElpiO6doigMbMSqp8ZDL_rq1xu51J5Syw,2237
|
|
61
|
+
jambonz_sdk/schema/components/recognizer-sonioxOptions.schema.json,sha256=HkMiX5Ul4b4W0Lz4APle5UgKKwefPZ5rehcCUg96pqU,1686
|
|
62
|
+
jambonz_sdk/schema/components/recognizer-speechmaticsOptions.schema.json,sha256=0q6ycpeTSFjc-cd0bBZyJCB2sw82633TXU7EmITIECA,3642
|
|
63
|
+
jambonz_sdk/schema/components/recognizer-verbioOptions.schema.json,sha256=gq64hfKwf56iF-MmpSaeZZjcfP5A1gGdIgLHauCa0xg,1438
|
|
64
|
+
jambonz_sdk/schema/components/recognizer.schema.json,sha256=M0RZFvNHsedZ7TVjKGen49hwutZv5lzIG5_1HK8up9c,9073
|
|
65
|
+
jambonz_sdk/schema/components/synthesizer.schema.json,sha256=-MiCdHn1N7ZXUokhGJU0dc3cc0zRhlOsAuOIltKmJPk,3302
|
|
66
|
+
jambonz_sdk/schema/components/target.schema.json,sha256=zBEvVYZIzMWexip2W_yvWn44dcc3pnWlLDDCQPN_Mmk,3473
|
|
67
|
+
jambonz_sdk/schema/components/vad.schema.json,sha256=IFgTWDImRoa2EctcvKSYB5iyDlXpUXNhAu8ldGPyn00,1869
|
|
68
|
+
jambonz_sdk/schema/verbs/alert.schema.json,sha256=bwV5K_8aT4RkJyd8kk5zqrAONEKtsDr0ieLqaC3tIGU,911
|
|
69
|
+
jambonz_sdk/schema/verbs/answer.schema.json,sha256=m7M3bsuwr0zwcatjgQeD4YSluWJeliAvT7ZNleB6a2E,690
|
|
70
|
+
jambonz_sdk/schema/verbs/conference.schema.json,sha256=hwtyuHNN5hAspCN7rL4CueNU8VySVSnBhFI6vpnhBV0,3798
|
|
71
|
+
jambonz_sdk/schema/verbs/config.schema.json,sha256=V1nSs2p_9Z_e1bhFHNPuBV6XXP8WeWyXpdml6cYtyt0,7109
|
|
72
|
+
jambonz_sdk/schema/verbs/deepgram_s2s.schema.json,sha256=xqcCwNZGeNrSCauRIiZ22re1IavS2y311p69DwACqkk,2284
|
|
73
|
+
jambonz_sdk/schema/verbs/dequeue.schema.json,sha256=-h1RdRKQsMqa9WeX0mbe7fSJd3GQ7uZ9p0A7AErg6Zs,1407
|
|
74
|
+
jambonz_sdk/schema/verbs/dial.schema.json,sha256=-khc5zsn-oP-p5qEr2fIKYzRITqs48IrO45MIYWzF9Y,7266
|
|
75
|
+
jambonz_sdk/schema/verbs/dialogflow.schema.json,sha256=aLoZ_wru_ZR2-rBN7MvkjbWSMyFKKgEPJZNsT-nDRNU,4416
|
|
76
|
+
jambonz_sdk/schema/verbs/dtmf.schema.json,sha256=2gwOII-xdbfwDnKE09Ds-D1bhQPIiHchCy6714ke91U,1147
|
|
77
|
+
jambonz_sdk/schema/verbs/dub.schema.json,sha256=ECEg6hOq_WigemwwDpl1WXsqf_JgqBrSbnPQZJO-Azc,2521
|
|
78
|
+
jambonz_sdk/schema/verbs/elevenlabs_s2s.schema.json,sha256=8gZT2yiqngY2nEqOKH1I0dqxjHnqwpl90SVc-0ndkuA,2508
|
|
79
|
+
jambonz_sdk/schema/verbs/enqueue.schema.json,sha256=xTLo7LNm8o8w-jNuBQJw83RNHV5AJN6wkDbT5INvS5c,1767
|
|
80
|
+
jambonz_sdk/schema/verbs/gather.schema.json,sha256=ee9KndAfUzGovbgZYc8j9Jhwn_Bj-oFsXq7WlPWNFsg,6181
|
|
81
|
+
jambonz_sdk/schema/verbs/google_s2s.schema.json,sha256=XPuLP0Py0mwCnggfbKQq_sFyvqIjdidPchFG-kY3xUw,1035
|
|
82
|
+
jambonz_sdk/schema/verbs/hangup.schema.json,sha256=QGoorQDijZpF9B9npjXQazfDxCnD50PshI4awEaNKV8,888
|
|
83
|
+
jambonz_sdk/schema/verbs/leave.schema.json,sha256=Iwy8Qe7qZGFNnW9bTmBTR7mySEXd3Kc-JshEB9XI7M0,574
|
|
84
|
+
jambonz_sdk/schema/verbs/listen.schema.json,sha256=azmsc5sQxTdTLTCYPbouXh_E6y1e2QcWLPPfx0WAgqM,4061
|
|
85
|
+
jambonz_sdk/schema/verbs/llm.schema.json,sha256=9jCYQxeLVaWVarKal3Zu2ajy3yOQ6LzqEv0H5jO_X6k,1234
|
|
86
|
+
jambonz_sdk/schema/verbs/message.schema.json,sha256=FNygt6xo_ff0EyOzqrOD0NVG7Df7ZyjvwLfRAyW8Ua0,2233
|
|
87
|
+
jambonz_sdk/schema/verbs/openai_s2s.schema.json,sha256=nWYihUfihZQg6azl-PKb9caLNfKNPPb22MyLK2h2Hns,1035
|
|
88
|
+
jambonz_sdk/schema/verbs/pause.schema.json,sha256=m-lgem141QCFcR9x1HEntDrV_IRwWsdVkP3z84Bjj3M,837
|
|
89
|
+
jambonz_sdk/schema/verbs/pipeline.schema.json,sha256=ilniLadTkJLjW8eW0aXCHd5V8RJwXY8bCNIq4HQLe6A,8867
|
|
90
|
+
jambonz_sdk/schema/verbs/play.schema.json,sha256=uf4k54-iuH1p7ctQsiKd5BKVTiy2aHNa3OCJnr-TpU0,2442
|
|
91
|
+
jambonz_sdk/schema/verbs/redirect.schema.json,sha256=8HxGjFA0mbJKcl8ZsyiD9b0edOzxkp1dVsA962z7lWI,1085
|
|
92
|
+
jambonz_sdk/schema/verbs/rest_dial.schema.json,sha256=K913G1pLVAxx4msjf2We7V3RGVEvyNWbeTRSmpJ3mEM,2841
|
|
93
|
+
jambonz_sdk/schema/verbs/s2s.schema.json,sha256=YPMjwPfq_VfQOtQscBIKFaK0OHiDw1LH8j5GxSJnGpw,912
|
|
94
|
+
jambonz_sdk/schema/verbs/say.schema.json,sha256=0Mhaw3DgvIylFJn8v6weO07wKzsgBHNueEXouEyBTtk,3521
|
|
95
|
+
jambonz_sdk/schema/verbs/sip-decline.schema.json,sha256=10iWST4JIwGrT1yP758YnEaijPyt-A7i-1Rg6yYJUd0,1404
|
|
96
|
+
jambonz_sdk/schema/verbs/sip-refer.schema.json,sha256=ogvdMtq8oP452SzR0lw0x-jmPkRtaUmiHa-4FY-GMlw,1720
|
|
97
|
+
jambonz_sdk/schema/verbs/sip-request.schema.json,sha256=czrONgdLCErVpV5wHw_i4YZyqyIgD1GeiVrgswKsBvw,1430
|
|
98
|
+
jambonz_sdk/schema/verbs/stream.schema.json,sha256=Xs3H3GSfdgul-spNREGKOyEiIofvFW6mIhRKjGsrGTg,2930
|
|
99
|
+
jambonz_sdk/schema/verbs/tag.schema.json,sha256=VKzVKh-YOwJxnLFrj9nFBzV0JFc7MyYzmOnjnzJ3KwA,1153
|
|
100
|
+
jambonz_sdk/schema/verbs/transcribe.schema.json,sha256=5cM1CYcdo-rFCE5wRDIqFtpEOf4v4BZs-yLjZc37tSE,1851
|
|
101
|
+
jambonz_sdk/schema/verbs/ultravox_s2s.schema.json,sha256=5QpPMgfQq3RTzWve3U6fKeZPst5oUGYO1n7OfiKWPl0,1017
|
|
102
|
+
jambonz_sdk/types/__init__.py,sha256=o0dkleGg8jqvORhD_mXumuos-NPisyu_CwTa-XG7kUQ,2428
|
|
103
|
+
jambonz_sdk/types/components.py,sha256=QHykPAfdDrlgmedmJykPUU5QZwi8ZiFbQkdgnumBmQk,5745
|
|
104
|
+
jambonz_sdk/types/rest.py,sha256=CFX0J-deBMoG8oXtoJzFIRBBKbjTULaUOnsV-mx09i8,1206
|
|
105
|
+
jambonz_sdk/types/session.py,sha256=kl2lv9z0aCfq9nD5nFzqRjVjVDeAERA_c9U4HUzqEQA,1305
|
|
106
|
+
jambonz_sdk/types/verbs.py,sha256=cOirvlP8gYnNK_JGjJ2FAdcMweZB3N9_4U3tv2vjqU8,12129
|
|
107
|
+
jambonz_sdk/webhook/__init__.py,sha256=JU-KEgTFn1uj8CPFKhFF_fUuwfElDR3hcv6nyK8tt9E,307
|
|
108
|
+
jambonz_sdk/webhook/middleware.py,sha256=8FuqDRJe6bOFLinU-_hTJCD_tOPxIMp2iHs4tY1SAqo,1931
|
|
109
|
+
jambonz_sdk/webhook/response.py,sha256=yL1JE-VjCfU2RPERA4-dl73iYqS9qQYMw2rAZyG80zE,1325
|
|
110
|
+
jambonz_sdk/websocket/__init__.py,sha256=13Xlg8FUF8BuVEqp7TtfNS9mfJR7ooQWtST-1g7ypNo,425
|
|
111
|
+
jambonz_sdk/websocket/audio_client.py,sha256=fjJH7XK0jCX8WR0mnn00oQPs9uqvp9jYq1azAyva3pQ,369
|
|
112
|
+
jambonz_sdk/websocket/audio_stream.py,sha256=JmkxP2oEpq0sA0jsuCp2I7g2Ai4PouC0H27mucnRXi4,5471
|
|
113
|
+
jambonz_sdk/websocket/client.py,sha256=HMlcZoOVzYH0pQY54pPgv7J063nKT-95ZJ2Y3u3hvsA,6324
|
|
114
|
+
jambonz_sdk/websocket/endpoint.py,sha256=yDwfIdVP-JKovUdHOzA_mFO_hsd3jh-sNtDaOnQqMIA,6394
|
|
115
|
+
jambonz_sdk/websocket/router.py,sha256=n04A-rJ3rQrLm3bcKLBB67Niu6PRPa-zDomyY4Uboj4,2879
|
|
116
|
+
jambonz_sdk/websocket/session.py,sha256=0Ooztm_Pqs2uYTbDZvswrRKi1ZFixaoDAVd7ML5pMg8,9248
|
|
117
|
+
jambonz_python_sdk-0.2.0.dist-info/METADATA,sha256=lUR1pYfQ0cMrYUJSglGRQyDYYRDdNHy7zNqF3YvfNc4,6367
|
|
118
|
+
jambonz_python_sdk-0.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
119
|
+
jambonz_python_sdk-0.2.0.dist-info/RECORD,,
|
jambonz_sdk/__init__.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""jambonz Python SDK.
|
|
2
|
+
|
|
3
|
+
A Python SDK for the jambonz CPaaS platform, providing:
|
|
4
|
+
|
|
5
|
+
- **Webhook**: HTTP transport for building jambonz voice apps
|
|
6
|
+
- **WebSocket**: Persistent connection transport for real-time voice AI
|
|
7
|
+
- **Client**: REST API client for call control and management
|
|
8
|
+
|
|
9
|
+
Quick start (webhook)::
|
|
10
|
+
|
|
11
|
+
from jambonz_sdk.webhook import WebhookResponse
|
|
12
|
+
|
|
13
|
+
jambonz = WebhookResponse()
|
|
14
|
+
jambonz.say(text="Hello!").hangup()
|
|
15
|
+
response_body = jambonz.to_json()
|
|
16
|
+
|
|
17
|
+
Quick start (websocket)::
|
|
18
|
+
|
|
19
|
+
from jambonz_sdk.websocket import create_endpoint
|
|
20
|
+
|
|
21
|
+
make_service, server = await create_endpoint(port=3000)
|
|
22
|
+
svc = make_service(path="/")
|
|
23
|
+
|
|
24
|
+
def handle_session(session):
|
|
25
|
+
session.say(text="Hello!").hangup()
|
|
26
|
+
await session.send()
|
|
27
|
+
|
|
28
|
+
svc.on("session:new", handle_session)
|
|
29
|
+
|
|
30
|
+
Quick start (REST client)::
|
|
31
|
+
|
|
32
|
+
from jambonz_sdk.client import JambonzClient
|
|
33
|
+
|
|
34
|
+
async with JambonzClient(base_url=url, account_sid=sid, api_key=key) as client:
|
|
35
|
+
call_sid = await client.calls.create({...})
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
__version__ = "0.1.0"
|
|
39
|
+
|
|
40
|
+
# Re-export main classes for convenience
|
|
41
|
+
from jambonz_sdk.client import JambonzClient
|
|
42
|
+
from jambonz_sdk.validator import JambonzValidator
|
|
43
|
+
from jambonz_sdk.verb_builder import VerbBuilder
|
|
44
|
+
from jambonz_sdk.webhook import WebhookResponse
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"JambonzClient",
|
|
48
|
+
"JambonzValidator",
|
|
49
|
+
"VerbBuilder",
|
|
50
|
+
"WebhookResponse",
|
|
51
|
+
"__version__",
|
|
52
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""HMAC-SHA256 webhook signature verification.
|
|
2
|
+
|
|
3
|
+
jambonz signs webhook requests with the header:
|
|
4
|
+
Jambonz-Signature: t=<timestamp>,v1=<signature>
|
|
5
|
+
|
|
6
|
+
The signature is computed as:
|
|
7
|
+
HMAC-SHA256(secret, timestamp + "." + raw_body)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import hashlib
|
|
13
|
+
import hmac
|
|
14
|
+
import time
|
|
15
|
+
|
|
16
|
+
DEFAULT_TOLERANCE = 300 # 5 minutes
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def verify_signature(
|
|
20
|
+
payload: bytes,
|
|
21
|
+
signature_header: str,
|
|
22
|
+
secret: str,
|
|
23
|
+
tolerance: int = DEFAULT_TOLERANCE,
|
|
24
|
+
) -> bool:
|
|
25
|
+
"""Verify a jambonz webhook signature.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
payload: Raw request body bytes.
|
|
29
|
+
signature_header: Value of the ``Jambonz-Signature`` header.
|
|
30
|
+
secret: The webhook signing secret.
|
|
31
|
+
tolerance: Maximum age in seconds for the timestamp (default 300).
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
True if the signature is valid.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValueError: If the signature header is malformed, the signature
|
|
38
|
+
doesn't match, or the timestamp is outside the tolerance window.
|
|
39
|
+
"""
|
|
40
|
+
parts: dict[str, str] = {}
|
|
41
|
+
for item in signature_header.split(","):
|
|
42
|
+
key, _, value = item.strip().partition("=")
|
|
43
|
+
parts[key] = value
|
|
44
|
+
|
|
45
|
+
timestamp_str = parts.get("t")
|
|
46
|
+
sig = parts.get("v1")
|
|
47
|
+
|
|
48
|
+
if not timestamp_str or not sig:
|
|
49
|
+
raise ValueError("Invalid Jambonz-Signature header format")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
timestamp = int(timestamp_str)
|
|
53
|
+
except (ValueError, TypeError) as exc:
|
|
54
|
+
raise ValueError("Invalid timestamp in Jambonz-Signature header") from exc
|
|
55
|
+
|
|
56
|
+
if tolerance > 0:
|
|
57
|
+
age = int(time.time()) - timestamp
|
|
58
|
+
if age > tolerance:
|
|
59
|
+
raise ValueError(
|
|
60
|
+
f"Signature timestamp too old: {age}s > {tolerance}s tolerance"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
signed_payload = f"{timestamp}.".encode() + payload
|
|
64
|
+
expected = hmac.new(
|
|
65
|
+
secret.encode(),
|
|
66
|
+
signed_payload,
|
|
67
|
+
hashlib.sha256,
|
|
68
|
+
).hexdigest()
|
|
69
|
+
|
|
70
|
+
if not hmac.compare_digest(expected, sig):
|
|
71
|
+
raise ValueError("Signature verification failed")
|
|
72
|
+
|
|
73
|
+
return True
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""REST API client for jambonz platform."""
|
|
2
|
+
|
|
3
|
+
from jambonz_sdk.client.api import (
|
|
4
|
+
CallsResource,
|
|
5
|
+
ConferencesResource,
|
|
6
|
+
JambonzClient,
|
|
7
|
+
QueuesResource,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CallsResource",
|
|
12
|
+
"ConferencesResource",
|
|
13
|
+
"JambonzClient",
|
|
14
|
+
"QueuesResource",
|
|
15
|
+
]
|