Files
dadoirie-ComfyUI_Dados_Nodes/utils/pinterest_oauth_handler.py
T
2025-04-30 17:47:50 +02:00

229 lines
8.2 KiB
Python

import webbrowser
from server import PromptServer # type: ignore pylint: disable=import-error
from aiohttp import ClientSession
from .pinterest_token import (
oauth_sessions, on_token_received,
get_token_for_node, is_token_expired, refresh_token,
create_auth_header, get_oauth_base_url, OAUTH_SCOPES
)
EVENT_PINTEREST_UPDATE = "/dadosNodes/PinterestNode"
def send_to_frontend(node_id, operation, message, data=None):
"""Send data to frontend with consistent format"""
payload = {
"operation": operation,
"node_id": node_id,
"message": message,
"id": node_id
}
if data:
payload.update(data)
print(f"Sending message to frontend: {EVENT_PINTEREST_UPDATE} for node {node_id}")
PromptServer.instance.send_sync(EVENT_PINTEREST_UPDATE, payload)
return True
async def start_oauth_flow(node_id, callback_function=None, app_id=None, app_secret=None, custom_scope=None):
"""Start the OAuth flow by generating a URL and opening the browser"""
if not app_id or not app_secret:
print("ERROR: Pinterest App ID or Secret not provided")
send_to_frontend(
node_id,
"oauth_error",
"Authentication failed: Pinterest App ID or Secret not provided"
)
return None
send_to_frontend(
node_id,
"oauth_started",
"Please authenticate with Pinterest in your browser"
)
try:
oauth_base_url = get_oauth_base_url()
auth_params = {
"client_id": app_id,
"redirect_uri": f"{oauth_base_url}/api/callback",
"response_type": "code",
"refreshable": "true",
"scope": custom_scope if custom_scope else OAUTH_SCOPES
}
query_string = "&".join([f"{key}={value}" for key, value in auth_params.items()])
auth_url = f"{oauth_base_url}/api/authorize?{query_string}"
if not auth_url:
print("ERROR: Failed to build authorization URL")
send_to_frontend(
node_id,
"oauth_error",
"Authentication failed: Unable to generate authorization URL"
)
return None
if node_id not in oauth_sessions:
oauth_sessions[node_id] = {}
oauth_sessions[node_id]["callback_function"] = callback_function
webbrowser.open(auth_url)
print(f"OAuth flow started for node {node_id} - browser opened")
return auth_url
except Exception as e:
print(f"Failed to start OAuth flow: {str(e)}")
send_to_frontend(
node_id,
"oauth_error",
f"Authentication failed: {str(e)}"
)
return None
def is_authenticated(node_id):
"""Check if a node is authenticated with Pinterest"""
token_data = get_token_for_node(node_id)
if not token_data:
print("No token found")
return False
return not is_token_expired(token_data)
async def refresh_authentication(node_id, app_id=None, app_secret=None):
"""Refresh authentication if token is expired"""
token_data = get_token_for_node(node_id)
if not token_data:
print("No token found")
return False
if is_token_expired(token_data):
print("Token is expired, needs refresh")
try:
return await refresh_token(node_id, app_id, app_secret)
except Exception as e:
print(f"Error refreshing token: {e}")
return False
return True
async def get_valid_auth_header(node_id, app_id=None, app_secret=None):
"""Get a valid auth header, refreshing token if needed"""
token_data = get_token_for_node(node_id)
if not token_data:
print("No access token available for node", node_id)
return None
if is_token_expired(token_data):
print("Token expired or will expire soon, refreshing...")
success = await refresh_authentication(node_id, app_id, app_secret)
if not success:
print("Failed to refresh token")
return None
token_data = get_token_for_node(node_id)
access_token = token_data.get('access_token')
return create_auth_header(access_token)
async def make_pinterest_request(node_id, endpoint, method="GET", data=None, app_id=None, app_secret=None):
"""Make a request to Pinterest API with authentication"""
headers = await get_valid_auth_header(node_id, app_id, app_secret)
if not headers:
send_to_frontend(
node_id,
"api_error",
"Authentication failed. Please re-authenticate."
)
return None
async with ClientSession() as session:
request_method = getattr(session, method.lower())
kwargs = {
"headers": headers,
"timeout": 30
}
if data and method != "GET":
kwargs["json"] = data
async with request_method(endpoint, **kwargs) as response:
if response.status != 200:
error_text = await response.text()
print(f"Error in Pinterest API request: {error_text}")
send_to_frontend(
node_id,
"api_error",
f"Pinterest API error: {response.status}"
)
return None
return await response.json()
async def handle_callback(node_id, code, callback_function, app_id=None, app_secret=None):
"""Handle OAuth callback with authorization code"""
try:
token_endpoint = "https://api.pinterest.com/v5/oauth/token"
oauth_base_url = get_oauth_base_url()
redirect_uri = f"{oauth_base_url}/api/callback"
data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": redirect_uri
}
if app_id and app_secret:
data["client_id"] = app_id
data["client_secret"] = app_secret
async with ClientSession() as session:
async with session.post(token_endpoint, data=data) as response:
if response.status != 200:
error_text = await response.text()
print(f"Error obtaining token: {error_text}")
return False
token_data = await response.json()
print("============= TOKEN RECEIVED =============")
print(f"Node ID: {node_id}")
if token_data:
print(f"Access Token: {token_data.get('access_token', 'None')[:10]}... (truncated)")
print(f"Refresh Token: {token_data.get('refresh_token', 'None')[:10]}... (truncated)")
print(f"Token Type: {token_data.get('token_type', 'None')}")
print(f"Expires In: {token_data.get('expires_in', 'None')} seconds")
print(f"Scope: {token_data.get('scope', 'None')}")
else:
print("WARNING: No token data received from Pinterest!")
print("==========================================")
auth_header = create_auth_header(token_data.get("access_token"))
async with session.get(
"https://api.pinterest.com/v5/user_account",
headers=auth_header,
timeout=30
) as user_response:
if user_response.status != 200:
print(f"Error getting user info: {await user_response.text()}")
username = "Unknown"
else:
user_data = await user_response.json()
username = user_data.get("username", "Unknown")
await on_token_received(node_id, token_data, username)
if callback_function:
await callback_function(node_id, username)
return True
except Exception as e:
print(f"Error handling callback: {str(e)}")
return False