fix(asterisk): update telecom route and recording fallback
This commit is contained in:
@@ -70,5 +70,11 @@ Default lab SIP accounts from `pjsip.conf`:
|
||||
- `2001` (operator A)
|
||||
- `2002` (operator B)
|
||||
|
||||
Telecom.kz note:
|
||||
- `87273901485 / 86205414@sip.telecom.kz` should be configured as a normal SIP account with `type=registration`.
|
||||
- Do not treat this number as an IP trunk unless Telecom provisions a separate IP-trunk product for it.
|
||||
- Inbound calls from this account are expected in `from-telecom` and should route to `7100`.
|
||||
- Keep the real Telecom password out of git and set it on the target host before reload.
|
||||
|
||||
Track 14 note:
|
||||
- `2001` and `2002` are allowed to keep multiple contacts so browser registration can coexist with `MicroSIP/Zoiper` in QA.
|
||||
|
||||
@@ -117,3 +117,16 @@ exten => h,1,StopMixMonitor()
|
||||
[mvpcc-operators]
|
||||
exten => _X.,1,Dial(PJSIP/${EXTEN},30)
|
||||
same => n,Hangup()
|
||||
|
||||
[from-telecom]
|
||||
; Incoming calls from Telecom.kz SIP account 86205414 / DID 87273901485.
|
||||
; Route them directly to the AI-first entrypoint 7100.
|
||||
exten => 86205414,1,NoOp(Incoming from telecom.kz DID 87273901485 -> AI)
|
||||
same => n,Set(CALLERID(dnid)=87273901485)
|
||||
same => n,Goto(from-softphones,7100,1)
|
||||
|
||||
exten => 87273901485,1,NoOp(Incoming from telecom.kz DID 87273901485 -> AI)
|
||||
same => n,Goto(from-softphones,7100,1)
|
||||
|
||||
exten => _X.,1,NoOp(Incoming from telecom.kz, DID=${EXTEN})
|
||||
same => n,Goto(from-softphones,7100,1)
|
||||
|
||||
@@ -82,3 +82,55 @@ type=aor
|
||||
max_contacts=1
|
||||
remove_existing=yes
|
||||
support_path=yes
|
||||
|
||||
;========================================================================
|
||||
; Telecom.kz SIP account (REGISTER auth, not IP trunk)
|
||||
; DID: 87273901485
|
||||
; SIP account: 86205414@sip.telecom.kz
|
||||
;========================================================================
|
||||
[telecom-kz-aor]
|
||||
type=aor
|
||||
max_contacts=1
|
||||
remove_existing=yes
|
||||
qualify_frequency=60
|
||||
support_path=yes
|
||||
|
||||
[telecom-kz-auth]
|
||||
type=auth
|
||||
auth_type=userpass
|
||||
username=86205414
|
||||
password=CHANGE_ME_TELECOM_KZ_PASSWORD
|
||||
|
||||
[telecom-kz]
|
||||
type=endpoint
|
||||
transport=transport-udp
|
||||
context=from-telecom
|
||||
disallow=all
|
||||
allow=alaw,ulaw
|
||||
aors=telecom-kz-aor
|
||||
outbound_auth=telecom-kz-auth
|
||||
from_user=86205414
|
||||
from_domain=sip.telecom.kz
|
||||
direct_media=no
|
||||
rtp_symmetric=yes
|
||||
force_rport=yes
|
||||
rewrite_contact=yes
|
||||
trust_id_inbound=yes
|
||||
send_rpid=yes
|
||||
identify_by=username
|
||||
language=ru
|
||||
|
||||
[telecom-kz-registration]
|
||||
type=registration
|
||||
transport=transport-udp
|
||||
outbound_auth=telecom-kz-auth
|
||||
server_uri=sip:sip.telecom.kz:5060
|
||||
client_uri=sip:86205414@sip.telecom.kz
|
||||
contact_user=86205414
|
||||
retry_interval=60
|
||||
forbidden_retry_interval=300
|
||||
expiration=300
|
||||
line=yes
|
||||
endpoint=telecom-kz
|
||||
support_path=yes
|
||||
auth_rejection_permanent=no
|
||||
|
||||
@@ -497,7 +497,7 @@ def upload_recording(
|
||||
url=f"{bridge._recording_service_url()}/recordings/import-upload",
|
||||
data=data,
|
||||
files={"file": (file_name, handle, mime_type or "application/octet-stream")},
|
||||
retry_reset=handle.seek(0),
|
||||
retry_reset=lambda: handle.seek(0),
|
||||
)
|
||||
return response.json()
|
||||
except httpx.HTTPStatusError as exc:
|
||||
|
||||
@@ -205,6 +205,74 @@ def test_post_json_bearer_first_falls_back_to_legacy(monkeypatch):
|
||||
assert DummyClient.seen_headers[1]["X-Role"] == "admin"
|
||||
|
||||
|
||||
def test_upload_recording_bearer_first_fallback_rewinds_file(monkeypatch, tmp_path):
|
||||
recording_path = tmp_path / "call.wav"
|
||||
recording_bytes = b"recording-payload"
|
||||
recording_path.write_bytes(recording_bytes)
|
||||
|
||||
class DummyClient:
|
||||
def __init__(self, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
class DummyResponse:
|
||||
def raise_for_status(self):
|
||||
return None
|
||||
|
||||
def json(self):
|
||||
return {"recording_id": "rec_uploaded"}
|
||||
|
||||
attempts: list[dict[str, object]] = []
|
||||
|
||||
def _fake_request_with_bridge_auth(client, *, retry_reset=None, headers=None, files=None, **kwargs):
|
||||
del client, headers, kwargs
|
||||
handle = files["file"][1]
|
||||
attempts.append(
|
||||
{
|
||||
"chunk": handle.read(),
|
||||
"has_retry_reset": callable(retry_reset),
|
||||
}
|
||||
)
|
||||
assert callable(retry_reset)
|
||||
retry_reset()
|
||||
attempts.append(
|
||||
{
|
||||
"chunk": handle.read(),
|
||||
"has_retry_reset": callable(retry_reset),
|
||||
}
|
||||
)
|
||||
return DummyResponse()
|
||||
|
||||
monkeypatch.setenv("ASTERISK_BRIDGE_AUTH_MODE", "bearer_first")
|
||||
monkeypatch.setenv("ASTERISK_BRIDGE_AUTH_FALLBACK_LEGACY", "1")
|
||||
monkeypatch.setenv("ASTERISK_BRIDGE_AUTH_USER", "ast-bridge")
|
||||
monkeypatch.setenv("ASTERISK_BRIDGE_AUTH_ROLE", "admin")
|
||||
monkeypatch.setenv("APP_TOKEN_SECRET", "track9-test-secret")
|
||||
monkeypatch.setattr(bridge_module.httpx, "Client", DummyClient)
|
||||
monkeypatch.setattr(bridge_module, "_request_with_bridge_auth", _fake_request_with_bridge_auth)
|
||||
|
||||
result = bridge_module._upload_recording(
|
||||
local_path=recording_path,
|
||||
call_id="call_upload_fallback",
|
||||
interaction_id="int_upload_fallback",
|
||||
source_event_id="src_upload_fallback",
|
||||
file_name="call.wav",
|
||||
mime_type="audio/wav",
|
||||
duration_seconds=3,
|
||||
)
|
||||
|
||||
assert result == {"recording_id": "rec_uploaded"}
|
||||
assert attempts == [
|
||||
{"chunk": recording_bytes, "has_retry_reset": True},
|
||||
{"chunk": recording_bytes, "has_retry_reset": True},
|
||||
]
|
||||
|
||||
|
||||
def test_assign_interaction_uses_patch(monkeypatch):
|
||||
class DummyResponse:
|
||||
status_code = 200
|
||||
|
||||
Reference in New Issue
Block a user