Skip to content

# Source code for terminusgps.twilio.caller

    import asyncio
    import os
    from typing import Any

    import twilio.rest
    from twilio.http.async_http_client import AsyncTwilioHttpClient

    class TwilioCaller:
        def __init__(
            self,
            client_sid: str | None = None,
            client_token: str | None = None,
            from_number: str | None = None,
            messaging_sid: str | None = None,
        ) -> None:
            """
            Sets Twilio client session variables.

            All parameters are optional, default values are pulled from a Django settings module.

            :param client_sid: A Twilio client session id.
            :type client_sid: :py:obj:`str` | :py:obj:`None`
            :param client_token: A Twilio client API token.
            :type client_token: :py:obj:`str` | :py:obj:`None`
            :param from_number: Phone number used to send notifications.
            :type from_number: :py:obj:`str` | :py:obj:`None`
            :param messaging_sid: A Twilio client messaging service session id.
            :type messaging_sid: :py:obj:`str` | :py:obj:`None`
            :returns: Nothing.
            :rtype: :py:obj:`None`

            """
            self._client_sid = client_sid or os.getenv("TWILIO_SID")
            self._client_token = client_token or os.getenv("TWILIO_TOKEN")
            self._from_number = from_number or os.getenv("TWILIO_FROM_NUMBER")
            self._messaging_sid = messaging_sid or os.getenv("TWILIO_MESSAGING_SID")

        def __enter__(self) -> "TwilioCaller":
            """Opens a context manager and creates an asyncronous Twilio client."""
            self.client = twilio.rest.Client(
                self.client_sid, self._client_token, http_client=AsyncTwilioHttpClient()
            )
            return self

        def __exit__(self, exc_type, exc_value, exc_tb) -> None:
            """Closes the context manager."""
            return None

        def create_notification(
            self, to_number: str, message: str, method: str = "sms"
        ) -> asyncio.Task[Any]:
            """
            Returns an awaitable notification task.

            Valid methods are ``"sms"``, ``"call"`` and ``"phone"``.

            :param to_number: A phone number to notify.
            :type to_number: :py:obj:`str`
            :param message: A notification message.
            :type message: :py:obj:`str`
            :param method: A notification method. Default is ``"sms"``.
            :type method: :py:obj:`str`
            :raises ValueError: If ``method`` is invalid.
            :returns: An awaitable task.
            :rtype: :py:obj:`~asyncio.Task`

            """
            match method:
                case "sms":
                    return asyncio.create_task(
                        self.create_sms(to_number=to_number, message=message)
                    )
                case "call" | "phone":
                    return asyncio.create_task(
                        self.create_call(to_number=to_number, message=message)
                    )
                case _:
                    raise ValueError(f"Unsupported TwilioCaller method '{method}'.")

async def create_call(self, to_number: str, message: str) -> None: """ Calls ``to_number`` and reads ``message`` aloud. :param to_number: A phone number. :type to_number: :py:obj:`str` :param message: A message to be read aloud. :type message: :py:obj:`str` :returns: Nothing. :rtype: :py:obj:`None` """ await self.client.calls.create_async( to=to_number, from_=self.from_number, twiml=f"<Response><Say>{message}</Say></Response>", )
async def create_sms(self, to_number: str, message: str) -> None: """ Texts ``message`` to ``to_number``. :param to_number: A phone number. :type to_number: :py:obj:`str` :param message: A message to be texted. :type message: :py:obj:`str` :returns: Nothing. :rtype: :py:obj:`None` """ await self.client.messages.create_async( to=to_number, from_=self.from_number, body=message, messaging_service_sid=self.messaging_sid, )
@property def client_sid(self) -> str | None: """ Client session id. :type: :py:obj:`str` """ return self._client_sid @property def from_number(self) -> str | None: """ Origin phone number. :type: :py:obj:`str` """ return self._from_number @property def messaging_sid(self) -> str | None: """ Messaging service session id. :type: :py:obj:`str` """ return self._messaging_sid