mirror of
https://github.com/langgenius/dify-plugin-sdks.git
synced 2026-07-22 10:25:23 -04:00
116 lines
4.7 KiB
Python
116 lines
4.7 KiB
Python
import urllib
|
|
from collections.abc import Mapping
|
|
from typing import Any
|
|
|
|
import requests
|
|
from werkzeug import Request
|
|
|
|
from dify_plugin.entities.datasource import DatasourceOAuthCredentials
|
|
from dify_plugin.errors.tool import DatasourceOAuthError, ToolProviderCredentialValidationError
|
|
from dify_plugin.interfaces.datasource import DatasourceProvider
|
|
|
|
__TIMEOUT_SECONDS__ = 60 * 10
|
|
|
|
|
|
class NotionDatasourceProvider(DatasourceProvider):
|
|
API_VERSION = "2022-06-28" # Using a stable API version
|
|
_AUTH_URL = "https://api.notion.com/v1/oauth/authorize"
|
|
_TOKEN_URL = "https://api.notion.com/v1/oauth/token"
|
|
|
|
def _oauth_get_authorization_url(self, redirect_uri: str, system_credentials: Mapping[str, Any]) -> str:
|
|
"""
|
|
Generate the authorization URL for the Notion OAuth.
|
|
"""
|
|
params = {
|
|
"client_id": system_credentials["client_id"],
|
|
"response_type": "code",
|
|
"redirect_uri": redirect_uri,
|
|
"owner": "user",
|
|
}
|
|
return f"{self._AUTH_URL}?{urllib.parse.urlencode(params)}"
|
|
|
|
def _oauth_get_credentials(
|
|
self, redirect_uri: str, system_credentials: Mapping[str, Any], request: Request
|
|
) -> DatasourceOAuthCredentials:
|
|
"""
|
|
Get the credentials for the Notion OAuth.
|
|
"""
|
|
code = request.args.get("code")
|
|
if not code:
|
|
raise DatasourceOAuthError("No code provided")
|
|
|
|
data = {
|
|
"code": code,
|
|
"grant_type": "authorization_code",
|
|
"redirect_uri": redirect_uri,
|
|
}
|
|
headers = {"Accept": "application/json"}
|
|
auth = (system_credentials["client_id"], system_credentials["client_secret"])
|
|
response = requests.post(self._TOKEN_URL, data=data, auth=auth, headers=headers, timeout=__TIMEOUT_SECONDS__)
|
|
response_json = response.json()
|
|
access_token = response_json.get("access_token")
|
|
if not access_token:
|
|
raise DatasourceOAuthError(f"Error in Notion OAuth: {response_json}")
|
|
|
|
workspace_name = response_json.get("workspace_name")
|
|
workspace_icon = response_json.get("workspace_icon")
|
|
workspace_id = response_json.get("workspace_id")
|
|
|
|
return DatasourceOAuthCredentials(
|
|
name=workspace_name,
|
|
avatar_url=workspace_icon,
|
|
credentials={
|
|
"integration_secret": access_token,
|
|
"workspace_name": workspace_name,
|
|
"workspace_icon": workspace_icon,
|
|
"workspace_id": workspace_id,
|
|
},
|
|
)
|
|
|
|
def _oauth_refresh_credentials(
|
|
self, redirect_uri: str, system_credentials: Mapping[str, Any], credentials: Mapping[str, Any]
|
|
) -> DatasourceOAuthCredentials:
|
|
"""
|
|
Refresh the credentials for the Notion OAuth.
|
|
|
|
Note: Notion OAuth API does not support refresh tokens.
|
|
When the access token expires, users need to re-authorize through the OAuth flow.
|
|
"""
|
|
pass
|
|
|
|
def _validate_credentials(self, credentials: Mapping[str, Any]):
|
|
try:
|
|
# Check if integration_token is provided
|
|
if "integration_secret" not in credentials or not credentials.get("integration_secret"):
|
|
raise ToolProviderCredentialValidationError("Notion Integration Token is required.")
|
|
|
|
# Try to authenticate with Notion API by making a test request
|
|
integration_secret = credentials.get("integration_secret")
|
|
|
|
try:
|
|
# Initialize the Notion client and attempt to fetch the current user
|
|
headers = {
|
|
"Authorization": f"Bearer {integration_secret}",
|
|
"Notion-Version": self.API_VERSION,
|
|
"Content-Type": "application/json",
|
|
}
|
|
# Make a request to the users endpoint to validate the token
|
|
response = requests.get(
|
|
"https://api.notion.com/v1/users/me", headers=headers, timeout=__TIMEOUT_SECONDS__
|
|
)
|
|
if response.status_code == 401:
|
|
raise ToolProviderCredentialValidationError("Invalid Notion Integration Token.")
|
|
elif response.status_code != 200:
|
|
raise ToolProviderCredentialValidationError(
|
|
f"Failed to connect to Notion API: {response.status_code} {response.text}"
|
|
)
|
|
else:
|
|
return True
|
|
except requests.RequestException as e:
|
|
raise ToolProviderCredentialValidationError(
|
|
f"Network error when connecting to Notion API: {e!s}"
|
|
) from e
|
|
|
|
except Exception as e:
|
|
raise ToolProviderCredentialValidationError(str(e)) from e
|