Files
Harry 2ea9b98a92 feat(gmail_trigger): improve attachment processing and metadata updates
- Enhanced the GmailMessageAddedEvent class to support additional attachment types and improved metadata extraction.
- Updated methods for handling inline content and external links, ensuring better integration with attachments.
- Revised the output schema in the YAML to include new fields for attachment metadata, improving clarity and usability.
2025-11-05 20:20:30 +08:00

125 lines
4.3 KiB
Python

from __future__ import annotations
import urllib.parse
from collections.abc import Mapping, Sequence
from typing import Any
import requests
from werkzeug import Request
from dify_plugin.entities.trigger import Variables
from dify_plugin.errors.trigger import EventIgnoreError
from dify_plugin.interfaces.trigger import Event
class GoogleCalendarEventBase(Event):
"""Shared helpers for Google Calendar trigger events."""
_CAL_BASE = "https://www.googleapis.com/calendar/v3"
def _collect_events(self, payload: Mapping[str, Any], key: str) -> list[dict[str, Any]]:
raw_items = payload.get(key)
if not isinstance(raw_items, Sequence):
return []
collected: list[dict[str, Any]] = []
for item in raw_items:
if isinstance(item, Mapping):
collected.append(dict(item))
return collected
def _resolve_calendar_id(self, payload: Mapping[str, Any], parameters: Mapping[str, Any]) -> str:
subscription_parameters: Mapping[str, Any] = {}
if getattr(self.runtime, "subscription", None):
subscription_parameters = self.runtime.subscription.parameters or {}
calendar_id = payload.get("calendarId") or parameters.get("calendar_id") or subscription_parameters.get("calendar_id") or "primary"
return str(calendar_id)
def _get_access_token(self) -> str:
credentials: Mapping[str, Any] = {}
if getattr(self.runtime, "credentials", None):
credentials = self.runtime.credentials or {}
token = credentials.get("access_token")
if not token:
raise ValueError("Missing Google Calendar OAuth access token in runtime credentials")
return str(token)
def _enrich_events(
self,
*,
calendar_id: str,
events: list[dict[str, Any]],
include_deleted: bool,
) -> list[dict[str, Any]]:
if not events:
return events
access_token = self._get_access_token()
headers = {"Authorization": f"Bearer {access_token}"}
encoded_calendar = urllib.parse.quote(calendar_id, safe="@._-")
enriched: list[dict[str, Any]] = []
for event in events:
event_id = str(event.get("id") or "").strip()
if not event_id:
continue
encoded_event = urllib.parse.quote(event_id, safe="@._-")
params = {"showDeleted": "true"} if include_deleted else None
try:
resp = requests.get(
f"{self._CAL_BASE}/calendars/{encoded_calendar}/events/{encoded_event}",
headers=headers,
params=params,
timeout=10,
)
except requests.RequestException:
enriched.append(event)
continue
if resp.status_code == 200:
try:
enriched.append(resp.json() or {})
except Exception:
enriched.append(event)
elif resp.status_code == 404 and include_deleted:
enriched.append(event)
else:
enriched.append(event)
# Fallback to original list if enrichment resulted in empty collection
return enriched or events
def _build_variables(
self,
*,
payload: Mapping[str, Any],
calendar_id: str,
events: list[dict[str, Any]],
) -> Variables:
if not events:
raise EventIgnoreError()
variables = {
"calendar_id": calendar_id,
"resource_state": payload.get("resourceState"),
"resource_id": payload.get("resourceId"),
"channel_id": payload.get("channelId"),
"next_sync_token": payload.get("nextSyncToken"),
"events": events,
}
include_cancelled = payload.get("includeCancelled")
if include_cancelled is not None:
variables["include_cancelled"] = include_cancelled
return Variables(variables=variables)
def _ensure_events_or_raise(self, events: list[dict[str, Any]]) -> None:
if not events:
raise EventIgnoreError()
def _validate_request(self, request: Request) -> None:
# Placeholder for future validation hooks (mirrors Gmail event structure).
_ = request
return