|
| 1 | +import time |
| 2 | +from collections.abc import Mapping |
| 3 | +from typing import Any |
| 4 | + |
| 5 | +from werkzeug import Request, Response |
| 6 | + |
| 7 | +from dify_plugin.entities.oauth import TriggerOAuthCredentials |
| 8 | +from dify_plugin.entities.provider_config import CredentialType |
| 9 | +from dify_plugin.entities.trigger import EventDispatch, Subscription, UnsubscribeResult |
| 10 | +from dify_plugin.errors.trigger import ( |
| 11 | + SubscriptionError, |
| 12 | + TriggerDispatchError, |
| 13 | + TriggerProviderCredentialValidationError, |
| 14 | + TriggerProviderOAuthError, |
| 15 | + UnsubscribeError, |
| 16 | +) |
| 17 | +from dify_plugin.interfaces.trigger import Trigger, TriggerSubscriptionConstructor |
| 18 | + |
| 19 | + |
| 20 | +class {{ .PluginName | SnakeToCamel }}Trigger(Trigger): |
| 21 | + """ |
| 22 | + Handle the webhook event dispatch. |
| 23 | + """ |
| 24 | + def _dispatch_event(self, subscription: Subscription, request: Request) -> EventDispatch: |
| 25 | + payload: Mapping[str, Any] = self._validate_payload(request) |
| 26 | + response = Response(response='{"status": "ok"}', status=200, mimetype="application/json") |
| 27 | + events: list[str] = self._dispatch_trigger_events(payload=payload) |
| 28 | + return EventDispatch(events=events, response=response) |
| 29 | + |
| 30 | + def _dispatch_trigger_events(self, payload: Mapping[str, Any]) -> list[str]: |
| 31 | + """Dispatch events based on webhook payload.""" |
| 32 | + events = [] |
| 33 | + # Get the event type from the payload |
| 34 | + event_type = payload.get("type", "") |
| 35 | + |
| 36 | + if event_type.startswith("my-event-type"): |
| 37 | + events.append("{{ .PluginName }}_event") |
| 38 | + |
| 39 | + return events |
| 40 | + |
| 41 | + def _validate_payload(self, request: Request) -> Mapping[str, Any]: |
| 42 | + try: |
| 43 | + payload = request.get_json(force=True) |
| 44 | + if not payload: |
| 45 | + raise TriggerDispatchError("Empty request body") |
| 46 | + return payload |
| 47 | + except TriggerDispatchError: |
| 48 | + raise |
| 49 | + except Exception as exc: |
| 50 | + raise TriggerDispatchError(f"Failed to parse payload: {exc}") from exc |
| 51 | + |
| 52 | +class {{ .PluginName | SnakeToCamel }}SubscriptionConstructor(TriggerSubscriptionConstructor): |
| 53 | + """Manage {{ .PluginName }} trigger subscriptions.""" |
| 54 | + |
| 55 | + def _validate_api_key(self, credentials: dict[str, Any]) -> None: |
| 56 | + api_key = credentials.get("api_key") |
| 57 | + if not api_key: |
| 58 | + raise TriggerProviderCredentialValidationError("API key is required to validate credentials.") |
| 59 | + |
| 60 | + def _create_subscription( |
| 61 | + self, |
| 62 | + endpoint: str, |
| 63 | + parameters: Mapping[str, Any], |
| 64 | + credentials: Mapping[str, Any], |
| 65 | + credential_type: CredentialType, |
| 66 | + ) -> Subscription: |
| 67 | + |
| 68 | + events: list[str] = parameters.get("events", []) |
| 69 | + |
| 70 | + # Replace this placeholder with API calls to register a webhook |
| 71 | + return Subscription( |
| 72 | + expires_at=int(time.time()) + 7 * 24 * 60 * 60, |
| 73 | + endpoint=endpoint, |
| 74 | + properties={ |
| 75 | + "external_id": "example-subscription", |
| 76 | + "events": events, |
| 77 | + }, |
| 78 | + ) |
| 79 | + |
| 80 | + def _delete_subscription( |
| 81 | + self, |
| 82 | + subscription: Subscription, |
| 83 | + credentials: Mapping[str, Any], |
| 84 | + credential_type: CredentialType, |
| 85 | + ) -> UnsubscribeResult: |
| 86 | + # Tear down any remote subscription that was created in `_subscribe`. |
| 87 | + return UnsubscribeResult(success=True, message="Subscription removed.") |
| 88 | + |
| 89 | + def _refresh_subscription( |
| 90 | + self, |
| 91 | + subscription: Subscription, |
| 92 | + credentials: Mapping[str, Any], |
| 93 | + credential_type: CredentialType, |
| 94 | + ) -> Subscription: |
| 95 | + # Extend the subscription lifetime or renew tokens with your upstream service. |
| 96 | + return Subscription( |
| 97 | + expires_at=int(time.time()) + 7 * 24 * 60 * 60, |
| 98 | + endpoint=subscription.endpoint, |
| 99 | + properties=subscription.properties, |
| 100 | + ) |
0 commit comments