# Copyright (c) 2025 Patrick Motsch # All rights reserved. """ Utility functions for automation feature. Moved from interfaces/interfaceDbChatbot.py. """ import json from typing import Dict, Any from datetime import datetime, UTC def parseScheduleToCron(schedule: str) -> Dict[str, Any]: """Parse schedule string to cron kwargs for APScheduler""" parts = schedule.split() if len(parts) != 5: raise ValueError(f"Invalid schedule format: {schedule}") return { "minute": parts[0], "hour": parts[1], "day": parts[2], "month": parts[3], "day_of_week": parts[4] } def planToPrompt(plan: Dict) -> str: """Convert plan structure to prompt string for workflow execution""" return plan.get("userMessage", plan.get("overview", "Execute automation workflow")) def replacePlaceholders(template: str, placeholders: Dict[str, str]) -> str: """Replace placeholders in template with actual values. Placeholder format: {{KEY:PLACEHOLDER_NAME}} or {{TIMESTAMP}}""" result = template # Replace TIMESTAMP placeholder first (calculated placeholder, not from parameters) timestampPattern = "{{TIMESTAMP}}" if timestampPattern in result: timestamp = datetime.now(UTC).strftime("%Y%m%d_%H%M%S") result = result.replace(timestampPattern, timestamp) for placeholderName, value in placeholders.items(): pattern = f"{{{{KEY:{placeholderName}}}}}" # Check if placeholder is in an array context like ["{{KEY:...}}"] # If value is a JSON array/dict, we should replace the entire ["{{KEY:...}}"] with the array arrayPattern = f'["{pattern}"]' if arrayPattern in result: # Check if value is a JSON array/dict isArrayValue = False arrayValue = None if isinstance(value, (list, dict)): isArrayValue = True arrayValue = json.dumps(value) elif isinstance(value, str): try: parsed = json.loads(value) if isinstance(parsed, (list, dict)): isArrayValue = True arrayValue = value # Already valid JSON string except (json.JSONDecodeError, ValueError): pass if isArrayValue: # Replace ["{{KEY:...}}"] with the array value result = result.replace(arrayPattern, arrayValue) continue # Skip the regular replacement below # Regular replacement - check if in quoted context patternStart = result.find(pattern) isQuoted = False if patternStart > 0: charBefore = result[patternStart - 1] if patternStart > 0 else None patternEnd = patternStart + len(pattern) charAfter = result[patternEnd] if patternEnd < len(result) else None if charBefore == '"' and charAfter == '"': isQuoted = True # Handle different value types if isinstance(value, (list, dict)): # Python list/dict - convert to JSON replacement = json.dumps(value) elif isinstance(value, str): # String value - check if it's a JSON string representing list/dict try: parsed = json.loads(value) if isinstance(parsed, (list, dict)): # It's a JSON string of a list/dict if isQuoted: # In quoted context, escape the JSON string escaped = json.dumps(value) replacement = escaped[1:-1] # Remove outer quotes else: # In unquoted context, use JSON directly replacement = value else: # It's a JSON string of a primitive if isQuoted: escaped = json.dumps(value) replacement = escaped[1:-1] else: replacement = value except (json.JSONDecodeError, ValueError): # Not valid JSON - treat as plain string if isQuoted: escaped = json.dumps(value) replacement = escaped[1:-1] else: replacement = value else: # Numbers, booleans, None - convert to string replacement = str(value) result = result.replace(pattern, replacement) return result