forked from keephq/keep
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feat-add-last-updated-timestamp-to-mappings
- Loading branch information
Showing
10 changed files
with
309 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
title: 'Ntfy.sh' | ||
sidebarTitle: 'Ntfy.sh Provider' | ||
description: 'Ntfy.sh allows you to send notifications to your devices' | ||
--- | ||
|
||
## Authentication Parameters | ||
|
||
The Ntfy.sh provider requires the following authentication parameters: | ||
|
||
- `Ntfy Access Token`: The access token for the Ntfy.sh account. This is required for the Ntfy.sh provider. | ||
- `Ntfy Host URL`: (For self-hosted Ntfy) The URL of the self-hosted Ntfy instance in the format `https://ntfy.example.com`. | ||
- `Ntfy Username`: (For self-hosted Ntfy) The username for the self-hosted Ntfy instance. | ||
- `Ntfy Password`: (For self-hosted Ntfy) The password for the self-hosted Ntfy instance. | ||
- `Ntfy Subcription Topic`: Required. The topic to which the notification will be sent. | ||
|
||
## Connecting with the Provider | ||
|
||
Obtain Ntfy Access Token (For Ntfy.sh only) | ||
|
||
1. Create an account on [Ntfy.sh](https://ntfy.sh/). | ||
2. After logging in, go to the [Access token](https://ntfy.sh/account) page. | ||
3. Click on the `CREATE ACCESS TOKEN`. Give it a label and select token expiration time and click on the `CREATE TOKEN` button. | ||
4. Copy the generated token. This will be used as the `Ntfy Access Token` in the provider settings. | ||
|
||
Self-Hosted Ntfy | ||
|
||
1. To self-host Ntfy, you can follow the instructions [here](https://docs.ntfy.sh/install/). | ||
2. For self-hosted Ntfy, you will need to provide the `Ntfy Host URL`, `Ntfy Username`, and `Ntfy Password` in the provider settings instead of the `Ntfy Access Token`. | ||
3. Create a new user for the self-hosted Ntfy instance and use the generated username and password in the provider settings. | ||
|
||
Subscribing to a Topic (For Ntfy.sh and self-hosted Ntfy) | ||
|
||
1. Login to your Ntfy.sh account. | ||
2. Click on `Subscribe to a topic` button and generate name for the topic and subscribe to it. | ||
3. Copy the generated topic name. This will be used as the `Ntfy Subcription Topic` in the provider settings. | ||
4. Reserve the topic and confiure access (Requires ntfy Pro) | ||
|
||
## Usefull Links | ||
|
||
- [Ntfy.sh](https://ntfy.sh/) | ||
- [To self-host Ntfy](https://docs.ntfy.sh/install/) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
## Change the variables | ||
|
||
1. Change the UID:GID in the docker-compose file to match your user and group id. | ||
|
||
## Run the docker-compose file | ||
|
||
```bash | ||
docker-compose up -d | ||
``` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
version: '2.3' | ||
|
||
services: | ||
ntfy: | ||
image: binwiederhier/ntfy | ||
container_name: ntfy | ||
command: | ||
- serve | ||
environment: | ||
- TZ=UTC # optional: set desired timezone | ||
user: UID:GID # optional: replace with your own user/group or uid/gid | ||
volumes: | ||
- /var/cache/ntfy:/var/cache/ntfy | ||
- /etc/ntfy:/etc/ntfy | ||
ports: | ||
- 80:80 | ||
healthcheck: # optional: remember to adapt the host:port to your environment | ||
test: | ||
[ | ||
'CMD-SHELL', | ||
"wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1", | ||
] | ||
interval: 60s | ||
timeout: 10s | ||
retries: 3 | ||
start_period: 40s | ||
restart: unless-stopped |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
""" | ||
NtfyProvider is a class that provides a way to send notifications to the user. | ||
""" | ||
|
||
import dataclasses | ||
|
||
import pydantic | ||
import base64 | ||
import requests | ||
from urllib.parse import urljoin | ||
|
||
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 NtfyProviderAuthConfig: | ||
""" | ||
NtfyProviderAuthConfig is a class that holds the authentication information for the NtfyProvider. | ||
""" | ||
|
||
access_token: str = dataclasses.field( | ||
metadata={ | ||
"required": False, | ||
"description": "Ntfy Access Token", | ||
"sensitive": True, | ||
}, | ||
default=None, | ||
) | ||
|
||
host: str = dataclasses.field( | ||
metadata={ | ||
"required": False, | ||
"description": "Ntfy Host URL (For self-hosted Ntfy only)", | ||
"sensitive": False, | ||
}, | ||
default=None, | ||
) | ||
|
||
username: str = dataclasses.field( | ||
metadata={ | ||
"required": False, | ||
"description": "Ntfy Username (For self-hosted Ntfy only)", | ||
"sensitive": False, | ||
}, | ||
default=None, | ||
) | ||
|
||
password: str = dataclasses.field( | ||
metadata={ | ||
"required": False, | ||
"description": "Ntfy Password (For self-hosted Ntfy only)", | ||
"sensitive": True, | ||
}, | ||
default=None, | ||
) | ||
|
||
subcription_topic: str = dataclasses.field( | ||
metadata={ | ||
"required": True, | ||
"description": "Ntfy Subcription Topic", | ||
"sensitive": False, | ||
}, | ||
default=None, | ||
) | ||
|
||
|
||
class NtfyProvider(BaseProvider): | ||
PROVIDER_DISPLAY_NAME = "Ntfy.sh" | ||
|
||
PROVIDER_SCOPES = [ | ||
ProviderScope( | ||
name="send_alert", | ||
mandatory=True, | ||
alias="Send Alert", | ||
) | ||
] | ||
|
||
def __init__( | ||
self, context_manager: ContextManager, provider_id: str, config: ProviderConfig | ||
): | ||
super().__init__(context_manager, provider_id, config) | ||
|
||
def dispose(self): | ||
pass | ||
|
||
def validate_scopes(self) -> dict[str, bool | str]: | ||
validated_scopes = {} | ||
validated_scopes["send_alert"] = True | ||
return validated_scopes | ||
|
||
def validate_config(self): | ||
self.authentication_config = NtfyProviderAuthConfig( | ||
**self.config.authentication | ||
) | ||
if self.authentication_config.access_token is None and self.authentication_config.host is None: | ||
raise ProviderException( | ||
"Either Access Token or Host is required" | ||
) | ||
if self.authentication_config.subcription_topic is None: | ||
raise ProviderException( | ||
"Subcription Topic is required" | ||
) | ||
if self.authentication_config.host is not None: | ||
if self.authentication_config.host.startswith("https://") or self.authentication_config.host.startswith("http://"): | ||
raise ProviderException( | ||
"Host should not start with https:// or http://" | ||
) | ||
if self.authentication_config.username is None: | ||
raise ProviderException( | ||
"Username is required when host is provided" | ||
) | ||
if self.authentication_config.password is None: | ||
raise ProviderException( | ||
"Password is required when host is provided" | ||
) | ||
|
||
def __get_auth_headers(self): | ||
if self.authentication_config.access_token is not None: | ||
return { | ||
"Authorization": f"Bearer {self.authentication_config.access_token}" | ||
} | ||
|
||
else: | ||
username = self.authentication_config.username | ||
password = self.authentication_config.password | ||
token = base64.b64encode(f"{username}:{password}".encode("utf-8")).decode("utf-8") | ||
|
||
return { | ||
"Authorization": f"Basic {token}" | ||
} | ||
|
||
def __send_alert(self, message=""): | ||
self.logger.debug(f"Sending notification to {self.authentication_config.subcription_topic}") | ||
|
||
NTFY_SUBSCRIPTION_TOPIC = self.authentication_config.subcription_topic | ||
|
||
if self.authentication_config.host is not None: | ||
base_url = self.authentication_config.host | ||
if not base_url.endswith("/"): | ||
base_url += "/" | ||
NTFY_URL = urljoin(base=base_url, url=NTFY_SUBSCRIPTION_TOPIC) | ||
else: | ||
NTFY_URL = urljoin(base="https://ntfy.sh/", url=NTFY_SUBSCRIPTION_TOPIC) | ||
|
||
try: | ||
response = requests.post(NTFY_URL, headers=self.__get_auth_headers(), data=message) | ||
|
||
if response.status_code == 401: | ||
raise ProviderException( | ||
f"Failed to send notification to {NTFY_URL}. Error: Unauthorized" | ||
) | ||
|
||
response.raise_for_status() | ||
return response.json() | ||
|
||
except Exception as e: | ||
raise ProviderException( | ||
f"Failed to send notification to {NTFY_URL}. Error: {e}" | ||
) | ||
|
||
def _notify(self, message=""): | ||
return self.__send_alert(message) | ||
|
||
if __name__ == "__main__": | ||
import logging | ||
|
||
logging.basicConfig(level=logging.DEBUG, handlers=[logging.StreamHandler()]) | ||
context_manager = ContextManager( | ||
tenant_id="singletenant", | ||
workflow_id="test", | ||
) | ||
|
||
import os | ||
|
||
ntfy_access_token = os.environ.get("NTFY_ACCESS_TOKEN") | ||
ntfy_host = os.environ.get("NTFY_HOST") | ||
ntfy_username = os.environ.get("NTFY_USERNAME") | ||
ntfy_password = os.environ.get("NTFY_PASSWORD") | ||
ntfy_subscription_topic = os.environ.get("NTFY_SUBSCRIPTION_TOPIC") | ||
|
||
if ntfy_access_token is None and ntfy_host is None: | ||
raise Exception("NTFY_ACCESS_TOKEN or NTFY_HOST is required") | ||
|
||
if ntfy_host is not None: | ||
if ntfy_username is None: | ||
raise Exception("NTFY_USERNAME is required") | ||
if ntfy_password is None: | ||
raise Exception("NTFY_PASSWORD is required") | ||
|
||
if ntfy_access_token is not None: | ||
config = ProviderConfig( | ||
description="Ntfy Provider", | ||
authentication={ | ||
"access_token": ntfy_access_token, | ||
"subcription_topic": ntfy_subscription_topic, | ||
}, | ||
) | ||
|
||
else: | ||
config = ProviderConfig( | ||
description="Ntfy Provider", | ||
authentication={ | ||
"host": ntfy_host, | ||
"username": ntfy_username, | ||
"password": ntfy_password, | ||
"subcription_topic": ntfy_subscription_topic, | ||
}, | ||
) | ||
|
||
provider = NtfyProvider( | ||
context_manager, | ||
provider_id="ntfy-keephq", | ||
config=config, | ||
) | ||
|
||
provider.notify(message="Test message from Keephq") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters