# Copyright (c) 2025 Patrick Motsch # All rights reserved. import logging import json import uuid from typing import Dict, Any from modules.aichat.datamodelFeatureAiChat import ActionResult, ActionDocument from modules.shared.configuration import APP_CONFIG logger = logging.getLogger(__name__) async def connectJira(self, parameters: Dict[str, Any]) -> ActionResult: try: apiUsername = parameters.get("apiUsername") if not apiUsername: return ActionResult.isFailure(error="apiUsername parameter is required") apiTokenConfigKey = parameters.get("apiTokenConfigKey") if not apiTokenConfigKey: return ActionResult.isFailure(error="apiTokenConfigKey parameter is required") apiUrl = parameters.get("apiUrl") if not apiUrl: return ActionResult.isFailure(error="apiUrl parameter is required") projectCode = parameters.get("projectCode") if not projectCode: return ActionResult.isFailure(error="projectCode parameter is required") issueType = parameters.get("issueType") if not issueType: return ActionResult.isFailure(error="issueType parameter is required") taskSyncDefinitionParam = parameters.get("taskSyncDefinition") if not taskSyncDefinitionParam: return ActionResult.isFailure(error="taskSyncDefinition parameter is required") # Parse taskSyncDefinition if isinstance(taskSyncDefinitionParam, str): try: taskSyncDefinition = json.loads(taskSyncDefinitionParam) except json.JSONDecodeError as e: return ActionResult.isFailure(error=f"taskSyncDefinition is not valid JSON: {str(e)}") elif isinstance(taskSyncDefinitionParam, dict): taskSyncDefinition = taskSyncDefinitionParam else: return ActionResult.isFailure(error=f"taskSyncDefinition must be a dict or JSON string, got {type(taskSyncDefinitionParam)}") # Get API token from APP_CONFIG apiToken = APP_CONFIG.get(apiTokenConfigKey) if not apiToken: errorMsg = f"{apiTokenConfigKey} not found in APP_CONFIG" logger.error(errorMsg) return ActionResult.isFailure(error=errorMsg) # Create ticket interface syncInterface = await self.services.ticket.connectTicket( taskSyncDefinition=taskSyncDefinition, connectorType="Jira", connectorParams={ "apiUsername": apiUsername, "apiToken": apiToken, "apiUrl": apiUrl, "projectCode": projectCode, "ticketType": issueType, }, ) # Store connection with unique ID connectionId = str(uuid.uuid4()) self._connections[connectionId] = { "interface": syncInterface, "taskSyncDefinition": taskSyncDefinition, "apiUrl": apiUrl, "projectCode": projectCode, } logger.info(f"JIRA connection established: {connectionId} (Project: {projectCode})") # Generate filename workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None filename = self._generateMeaningfulFileName( "jira_connection", "json", workflowContext, "connectJira" ) # Create connection info document connectionInfo = { "connectionId": connectionId, "apiUrl": apiUrl, "projectCode": projectCode, "issueType": issueType, } validationMetadata = self._createValidationMetadata( "connectJira", connectionId=connectionId, apiUrl=apiUrl, projectCode=projectCode ) document = ActionDocument( documentName=filename, documentData=json.dumps(connectionInfo, indent=2), mimeType="application/json", validationMetadata=validationMetadata ) return ActionResult.isSuccess(documents=[document]) except Exception as e: errorMsg = f"Error connecting to JIRA: {str(e)}" logger.error(errorMsg) return ActionResult.isFailure(error=errorMsg)