Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
"providers/documentation/pingdom-provider",
"providers/documentation/posthog-provider",
"providers/documentation/planner-provider",
"providers/documentation/plivo-provider",
"providers/documentation/postgresql-provider",
"providers/documentation/prometheus-provider",
"providers/documentation/pushover-provider",
Expand Down
17 changes: 17 additions & 0 deletions docs/providers/documentation/plivo-provider.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "Plivo Provider"
description: "Plivo Provider is a provider that allows to notify alerts via SMS using Plivo."
---
import AutoGeneratedSnippet from '/snippets/providers/plivo-snippet-autogenerated.mdx';

<AutoGeneratedSnippet />

## Connecting with the Provider

To use the Plivo Provider you'll need your Plivo Auth ID and Auth Token from the Plivo console.
How to find your Plivo Auth ID and Auth Token - [cx.plivo.com](https://cx.plivo.com/?utm_source=github&utm_medium=oss&utm_campaign=keep)

## Useful Links

- Plivo console - [cx.plivo.com](https://cx.plivo.com/?utm_source=github&utm_medium=oss&utm_campaign=keep)
- Plivo Messages API - https://www.plivo.com/docs/messaging/api/messages
34 changes: 34 additions & 0 deletions docs/snippets/providers/plivo-snippet-autogenerated.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{/* This snippet is automatically generated using scripts/docs_render_provider_snippets.py
Do not edit it manually, as it will be overwritten */}

## Authentication
This provider requires authentication.
- **auth_id**: Plivo Auth ID (required: True, sensitive: False)
- **auth_token**: Plivo Auth Token (required: True, sensitive: True)
- **from_phone_number**: Plivo source number or sender ID (required: True, sensitive: False)

Certain scopes may be required to perform specific actions or queries via the provider. Below is a summary of relevant scopes and their use cases:
- **send_sms**: The credentials can send SMS via the Plivo Messages API (mandatory)



## In workflows

This provider can be used in workflows.



As "action" to make changes or update data, example:
```yaml
actions:
- name: Query plivo
provider: plivo
config: "{{ provider.my_provider_name }}"
with:
message_body: {value} # The content of the SMS message to be sent. Defaults to "".
to_phone_number: {value} # The recipient's phone number. Defaults to "".
```



If you need workflow examples with this provider, please raise a [GitHub issue](https://github.com/keephq/keep/issues).
Binary file added keep-ui/public/icons/plivo-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 165 additions & 0 deletions keep/providers/plivo_provider/plivo_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"""
PlivoProvider is a class that implements the BaseProvider interface for Plivo SMS.
"""

import dataclasses

import plivo
import pydantic

from keep.contextmanager.contextmanager import ContextManager
from keep.exceptions.provider_exception import ProviderException
from keep.providers.base.base_provider import BaseProvider
from keep.providers.models.provider_config import ProviderConfig, ProviderScope


@pydantic.dataclasses.dataclass
class PlivoProviderAuthConfig:
"""Plivo authentication configuration."""

auth_id: str = dataclasses.field(
metadata={
"required": True,
"description": "Plivo Auth ID",
"sensitive": False,
"documentation_url": "https://www.plivo.com/docs/messaging/quickstart/python/",
}
)

auth_token: str = dataclasses.field(
metadata={
"required": True,
"description": "Plivo Auth Token",
"sensitive": True,
"documentation_url": "https://www.plivo.com/docs/messaging/quickstart/python/",
}
)

from_phone_number: str = dataclasses.field(
metadata={
"required": True,
"description": "Plivo source number or sender ID",
"sensitive": False,
"documentation_url": "https://www.plivo.com/docs/messaging/concepts/sms/",
}
)


class PlivoProvider(BaseProvider):
"""Send SMS via Plivo."""

PROVIDER_DISPLAY_NAME = "Plivo"
PROVIDER_CATEGORY = ["Collaboration"]
PROVIDER_SCOPES = [
ProviderScope(
name="send_sms",
description="The credentials can send SMS via the Plivo Messages API",
mandatory=True,
alias="Send SMS",
)
]

def __init__(
self, context_manager: ContextManager, provider_id: str, config: ProviderConfig
):
super().__init__(context_manager, provider_id, config)

def validate_scopes(self) -> dict[str, bool | str]:
# A Plivo send is billed and not idempotent (unlike Twilio's magic test
# number), so validate the credentials with a read instead of a test send.
validated_scopes = {}
try:
client = plivo.RestClient(
self.authentication_config.auth_id,
self.authentication_config.auth_token,
)
client.messages.list(limit=1)
validated_scopes["send_sms"] = True
except Exception as e:
self.logger.warning(
"Failed to validate scope send_sms",
extra={"reason": str(e)},
)
validated_scopes["send_sms"] = str(e)

return validated_scopes

def validate_config(self):
self.authentication_config = PlivoProviderAuthConfig(
**self.config.authentication
)

def dispose(self):
"""
No need to dispose of anything, so just do nothing.
"""
pass

def _notify(
self, message_body: str = "", to_phone_number: str = "", **kwargs: dict
):
"""
Send an SMS notification using the Plivo Messages API.
Args:
message_body (str, optional): The content of the SMS message to be sent. Defaults to "".
to_phone_number (str, optional): The recipient's phone number. Defaults to "".
"""
self.logger.debug("Notifying alert SMS via Plivo")

if not to_phone_number:
raise ProviderException(
f"{self.__class__.__name__} failed to notify alert SMS via Plivo: to_phone_number is required"
)
client = plivo.RestClient(
self.authentication_config.auth_id,
self.authentication_config.auth_token,
)
try:
self.logger.debug("Sending SMS via Plivo")
client.messages.create(
src=self.authentication_config.from_phone_number,
dst=to_phone_number,
text=message_body,
)
self.logger.debug("SMS sent via Plivo")
except Exception as e:
self.logger.warning(
"Failed to send SMS via Plivo", extra={"reason": str(e)}
)
raise ProviderException(
f"{self.__class__.__name__} failed to notify alert SMS via Plivo: {e}"
)


if __name__ == "__main__":
# Output debug messages
import logging

logging.basicConfig(level=logging.DEBUG, handlers=[logging.StreamHandler()])
context_manager = ContextManager(
tenant_id="singletenant",
workflow_id="test",
)
# Load environment variables
import os

plivo_auth_id = os.environ.get("PLIVO_AUTH_ID")
plivo_auth_token = os.environ.get("PLIVO_AUTH_TOKEN")
plivo_from_phone_number = os.environ.get("PLIVO_FROM_PHONE_NUMBER")
plivo_to_phone_number = os.environ.get("PLIVO_TO_PHONE_NUMBER")
# Initialize the provider and provider config
config = ProviderConfig(
description="Plivo Input Provider",
authentication={
"auth_id": plivo_auth_id,
"auth_token": plivo_auth_token,
"from_phone_number": plivo_from_phone_number,
},
)
provider = PlivoProvider(context_manager, provider_id="plivo", config=config)
provider.validate_scopes()
# Send SMS
provider.notify(
message_body="Keep Alert",
to_phone_number=plivo_to_phone_number,
)
Loading
Loading