Документация

Провайдерский API

Версия v2.3.1 · Обновлено

Провайдерский API#

Каждый модуль провайдера должен определять класс с именем Provider.

Класс должен наследоваться от:

app.notifiers.voice.base.BaseVoiceProvider

Минимальный провайдер#

from app.notifiers.voice.base import (
    BaseVoiceProvider,
    VoiceCallRequest,
    VoiceCallResult,
    VoiceProviderCapabilities,
)


class Provider(BaseVoiceProvider):
    """Minimal custom voice provider."""

    name = "example"

    capabilities = VoiceProviderCapabilities(
        tts=True,
        status_callback=False,
        dtmf_callback=False,
        status_polling=False,
    )

    def place_call(self, request: VoiceCallRequest) -> VoiceCallResult:
        """Place a voice call."""

        print(f"Calling {request.phone}: {request.text}")

        return VoiceCallResult(
            call_id="example-call-id",
            status="queued",
            raw={"provider": self.name},
        )

Методы провайдера#

Провайдер может реализовать:

place_call()
parse_callback()
get_call_status()
validate_config()

Обязателен только place_call().

Методы колбэков и опроса необязательны и зависят от того, что поддерживает ваш провайдер.

BaseVoiceProvider#

class BaseVoiceProvider:
    name = "base"

    capabilities = VoiceProviderCapabilities()

    def __init__(self, config: dict[str, Any] | None = None) -> None:
        self.config = config or {}

    @classmethod
    def validate_config(cls, config: dict[str, Any]) -> None:
        """Validate provider-specific configuration."""

    def place_call(self, request: VoiceCallRequest) -> VoiceCallResult:
        """Place a voice call."""

        raise NotImplementedError

    def parse_callback(
        self,
        payload: dict[str, Any],
        headers: dict[str, str] | None = None,
        raw_body: bytes | None = None,
        query_args: dict[str, Any] | None = None,
    ) -> list[VoiceCallCallbackEvent]:
        """Parse provider webhook callback."""

        return []

    def get_call_status(self, call_id: str) -> VoiceCallResult:
        """Return current call status."""

        raise NotImplementedError

Возможности#

Каждый провайдер должен объявлять свои возможности.

from app.notifiers.voice.base import VoiceProviderCapabilities


class Provider(BaseVoiceProvider):
    name = "mango"

    capabilities = VoiceProviderCapabilities(
        tts=True,
        status_callback=True,
        dtmf_callback=True,
        status_polling=False,
    )

tts#

Провайдер может принимать текст и воспроизводить его во время вызова.

status_callback#

Провайдер может отправлять колбэки вебхуков с изменениями статуса вызова.

Рекомендуемые статусы:

queued
ringing
answered
completed
failed
busy
no_answer
cancelled
unknown

dtmf_callback#

Провайдер может отправлять колбэки вебхуков, когда пользователь нажимает кнопки телефонной клавиатуры.

Пример:

1 -> acknowledge
2 -> resolve

status_polling#

Провайдер может возвращать статус вызова через запрос к API.

Это полезно, когда провайдер не поддерживает колбэки.

VoiceCallRequest#

place_call() получает один VoiceCallRequest.

def place_call(self, request: VoiceCallRequest) -> VoiceCallResult:
    ...

Поля#

ПолеОписание
request.phoneЦелевой номер телефона
request.textТекст, который должен быть произнесён во время вызова
request.alert_idИдентификатор алерта IncidentRelay
request.event_typeТип события уведомления: notification, reminder, escalation, test
request.callback_urlURL колбэка для событий статуса и DTMF
request.callback_secretСекрет колбэка, используемый в URL колбэка
request.severityУровень важности алерта
request.titleЗаголовок алерта
request.messageСообщение алерта
request.assigneeЧитаемое имя ответственного
request.teamSlug команды
request.action_hintsРекомендуемые действия с клавиатуры
request.metadataДополнительные метаданные IncidentRelay

Пример action_hints:

{
    "1": "acknowledge",
    "2": "resolve",
}

Пример metadata:

{
    "channel_id": 1,
    "channel_name": "infra-voice-critical",
    "channel_type": "voice_call",
}

VoiceCallResult#

place_call() и get_call_status() должны возвращать VoiceCallResult.

return VoiceCallResult(
    call_id="abc-123",
    status="queued",
    raw=response_data,
)

call_id#

Внешний идентификатор вызова, возвращаемый провайдером.

IncidentRelay сохраняет его как external_message_id.

Этот идентификатор позже используется для сопоставления колбэков провайдера с исходным уведомлением об алерте.

status#

Нормализованный статус провайдера.

Рекомендуемые значения:

queued
ringing
answered
completed
failed
busy
no_answer
cancelled
logged
unknown

raw#

Исходный ответ провайдера или полезная отладочная информация.

Не помещайте секреты в raw.

VoiceCallCallbackEvent#

parse_callback() должен возвращать список объектов VoiceCallCallbackEvent.

return [
    VoiceCallCallbackEvent(
        call_id="abc-123",
        event_type="dtmf",
        status="answered",
        digit="1",
        raw=payload,
    )
]

Поля#

ПолеОписание
call_idВнешний идентификатор вызова провайдера
event_typeНормализованный тип события: status, dtmf, error
statusСтатус вызова
digitЦифра DTMF, нажатая получателем вызова
actionНеобязательное нормализованное действие IncidentRelay
alert_idНеобязательный идентификатор алерта
messageНеобязательное читаемое сообщение колбэка
rawИсходная полезная нагрузка колбэка провайдера

Поддерживаемые действия:

acknowledge
resolve