Source code for sinch.domains.voice.helpers.v2.svaml.calls

from collections.abc import Sequence
from typing import Union, cast

from sinch.core.models.internal.utils import strip_unset
from sinch.core.sentinel import UNSET, UnsetOr
from sinch.domains.voice.helpers.v2.destinations import Destination
from sinch.domains.voice.helpers.v2.svaml.internal.utils import as_commands
from sinch.domains.voice.models.v2.svaml.types import (
    AnswerCommandDict,
    BridgeCallCommandDict,
    DialCommandDict,
    HangupCommandDict,
    PauseCommandDict,
    SvamlCommandDict,
)
from sinch.domains.voice.models.v2.types import (
    BaseCallDestinationDict,
    CallDestinationDict,
    CallOriginDict,
)


[docs] class Calls: """Helpers to build the call control SVAML commands."""
[docs] @staticmethod def answer() -> AnswerCommandDict: """ Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated. :returns: The ``answer`` command. :rtype: AnswerCommandDict """ return {"command": "answer"}
[docs] @staticmethod def bridge_call(name: str) -> BridgeCallCommandDict: """ Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge. Bridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created. :param name: Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically. :type name: str :returns: The ``bridgeCall`` command. :rtype: BridgeCallCommandDict """ return {"command": "bridgeCall", "bridge_name": name}
[docs] @staticmethod def dial( to: Union[str, BaseCallDestinationDict, CallDestinationDict], *, from_: UnsetOr[ Union[str, BaseCallDestinationDict, CallOriginDict] ] = UNSET, name: UnsetOr[str] = UNSET, timeout_duration_seconds: UnsetOr[int] = UNSET, max_duration_seconds: UnsetOr[int] = UNSET, on_answer: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, on_busy: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, on_reject: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, on_timeout: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, on_hangup: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, on_failure: UnsetOr[ Union[SvamlCommandDict, Sequence[SvamlCommandDict]] ] = UNSET, ) -> DialCommandDict: """ Initiates a new outbound call leg within the current session. This is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property. The `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous). :param to: Call destination: a phone number in E.164 format, a SIP URI, a WebSocket endpoint for real-time audio streaming or the Voice Relay service for real-time speech-to-text and text-to-speech. A string is parsed with :meth:`Destination.of`. :type to: Union[str, BaseCallDestinationDict, CallDestinationDict] :param from_: Call origin: a phone number in E.164 format or a SIP URI. A string is parsed with :meth:`Destination.of`. :type from_: UnsetOr[Union[str, BaseCallDestinationDict, CallOriginDict]] :param name: Identifier for this call leg within the session. Must be unique across all active call legs in the session. Other commands (e.g., `hangup`) can reference this name to target this specific leg. :type name: UnsetOr[str] :param timeout_duration_seconds: Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered. :type timeout_duration_seconds: UnsetOr[int] :param max_duration_seconds: Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached. :type max_duration_seconds: UnsetOr[int] :param on_answer: SVAML commands to be executed when the call is answered. :type on_answer: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :param on_busy: SVAML commands to be executed when the call is busy. :type on_busy: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :param on_reject: SVAML commands to be executed when the call is rejected. :type on_reject: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :param on_timeout: SVAML commands to be executed when the call is timed out. :type on_timeout: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :param on_hangup: SVAML commands to be executed when the call is hung up. :type on_hangup: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :param on_failure: SVAML commands to be executed when the call fails. :type on_failure: UnsetOr[Union[SvamlCommandDict, Sequence[SvamlCommandDict]]] :returns: The ``dial`` command. :rtype: DialCommandDict """ events = strip_unset( { "on_answer": as_commands(on_answer), "on_busy": as_commands(on_busy), "on_reject": as_commands(on_reject), "on_timeout": as_commands(on_timeout), "on_hangup": as_commands(on_hangup), "on_failure": as_commands(on_failure), } ) return cast( DialCommandDict, strip_unset( { "command": "dial", "to": Destination.of(to) if isinstance(to, str) else to, "from_": ( Destination.of(from_) if isinstance(from_, str) else from_ ), "call_name": name, "dial_timeout_duration_seconds": timeout_duration_seconds, "max_call_duration_seconds": max_duration_seconds, "events": events if events else UNSET, } ), )
[docs] @staticmethod def hangup(name: UnsetOr[str] = UNSET) -> HangupCommandDict: """ Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended. Any subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence. :param name: Name of the call leg to end, as set by `callName` in the `dial` command. If omitted, the current call leg is ended. :type name: UnsetOr[str] :returns: The ``hangup`` command. :rtype: HangupCommandDict """ return cast( HangupCommandDict, strip_unset({"command": "hangup", "call_name": name}), )
[docs] @staticmethod def pause(duration_milliseconds: int) -> PauseCommandDict: """ Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes. The pause does not affect call audio; the call remains connected and audio continues uninterrupted. :param duration_milliseconds: Duration of the pause in milliseconds. :type duration_milliseconds: int :returns: The ``pause`` command. :rtype: PauseCommandDict """ return { "command": "pause", "duration_milliseconds": duration_milliseconds, }