# Copyright (c) 2025 Patrick Motsch # All rights reserved. import logging import json from typing import Dict, Any from modules.datamodels.datamodelChat import ActionResult, ActionDocument logger = logging.getLogger(__name__) async def copyFile(self, parameters: Dict[str, Any]) -> ActionResult: try: connectionReference = parameters.get("connectionReference") if not connectionReference: return ActionResult.isFailure(error="connectionReference parameter is required") siteIdParam = parameters.get("siteId") if not siteIdParam: return ActionResult.isFailure(error="siteId parameter is required") sourceFolder = parameters.get("sourceFolder") if not sourceFolder: return ActionResult.isFailure(error="sourceFolder parameter is required") sourceFile = parameters.get("sourceFile") if not sourceFile: return ActionResult.isFailure(error="sourceFile parameter is required") destFolder = parameters.get("destFolder") if not destFolder: return ActionResult.isFailure(error="destFolder parameter is required") destFile = parameters.get("destFile") if not destFile: return ActionResult.isFailure(error="destFile parameter is required") # Extract siteId from document if it's a reference siteId = None if isinstance(siteIdParam, str): from modules.datamodels.datamodelDocref import DocumentReferenceList try: docList = DocumentReferenceList.from_string_list([siteIdParam]) chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList) if chatDocuments and len(chatDocuments) > 0: siteInfoJson = json.loads(chatDocuments[0].documentData) siteId = siteInfoJson.get("id") except: pass if not siteId: siteId = siteIdParam else: siteId = siteIdParam if not siteId: return ActionResult.isFailure(error="Could not extract siteId from parameter") # Get Microsoft connection connection = self.connection.getMicrosoftConnection(connectionReference) if not connection: return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference") # Copy file await self.services.sharepoint.copyFileAsync( siteId=siteId, sourceFolder=sourceFolder, sourceFile=sourceFile, destFolder=destFolder, destFile=destFile ) logger.info(f"Copied file in SharePoint: {sourceFolder}/{sourceFile} -> {destFolder}/{destFile}") # Generate filename workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None filename = self._generateMeaningfulFileName( "file_copy_result", "json", workflowContext, "copyFile" ) result = { "success": True, "siteId": siteId, "sourcePath": f"{sourceFolder}/{sourceFile}", "destPath": f"{destFolder}/{destFile}" } validationMetadata = self._createValidationMetadata( "copyFile", siteId=siteId, sourcePath=f"{sourceFolder}/{sourceFile}", destPath=f"{destFolder}/{destFile}" ) document = ActionDocument( documentName=filename, documentData=json.dumps(result, indent=2), mimeType="application/json", validationMetadata=validationMetadata ) return ActionResult.isSuccess(documents=[document]) except Exception as e: # Handle file not found gracefully if "itemNotFound" in str(e) or "404" in str(e): logger.warning(f"File not found for copy: {parameters.get('sourceFolder')}/{parameters.get('sourceFile')}") # Return success with skipped status workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None filename = self._generateMeaningfulFileName( "file_copy_result", "json", workflowContext, "copyFile" ) result = { "success": True, "skipped": True, "reason": "File not found (may not exist yet)" } validationMetadata = self._createValidationMetadata( "copyFile", skipped=True ) document = ActionDocument( documentName=filename, documentData=json.dumps(result, indent=2), mimeType="application/json", validationMetadata=validationMetadata ) return ActionResult.isSuccess(documents=[document]) errorMsg = f"Error copying file in SharePoint: {str(e)}" logger.error(errorMsg) return ActionResult.isFailure(error=errorMsg)