# Copyright (c) 2025 Patrick Motsch # All rights reserved. """ Upload File action for SharePoint operations. Uploads raw file content (bytes) to SharePoint. """ import logging import json import base64 from typing import Dict, Any from modules.workflows.methods.methodBase import action from modules.datamodels.datamodelChat import ActionResult, ActionDocument logger = logging.getLogger(__name__) @action async def uploadFile(self, parameters: Dict[str, Any]) -> ActionResult: """ Upload raw file content (bytes) to SharePoint. Parameters: - connectionReference (str, required): Microsoft connection label. - siteId (str, required): SharePoint site ID (from findSiteByUrl result) or document reference containing site info - folderPath (str, required): Folder path relative to site root - fileName (str, required): File name - content (str, required): Document reference containing file content as base64-encoded bytes Returns: - ActionResult with ActionDocument containing upload result """ 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") folderPath = parameters.get("folderPath") if not folderPath: return ActionResult.isFailure(error="folderPath parameter is required") fileName = parameters.get("fileName") if not fileName: return ActionResult.isFailure(error="fileName parameter is required") contentParam = parameters.get("content") if not contentParam: return ActionResult.isFailure(error="content 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 file content from document from modules.datamodels.datamodelDocref import DocumentReferenceList docList = DocumentReferenceList.from_string_list([contentParam] if isinstance(contentParam, str) else contentParam) chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList) if not chatDocuments or len(chatDocuments) == 0: return ActionResult.isFailure(error="Could not get file content from document reference") fileContentBase64 = chatDocuments[0].documentData # Decode base64 try: fileContent = base64.b64decode(fileContentBase64) except Exception as e: return ActionResult.isFailure(error=f"Could not decode base64 file content: {str(e)}") # 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") # Upload file uploadResult = await self.services.sharepoint.uploadFile( siteId=siteId, folderPath=folderPath, fileName=fileName, content=fileContent ) if "error" in uploadResult: return ActionResult.isFailure(error=f"Upload failed: {uploadResult['error']}") logger.info(f"Uploaded file to SharePoint: {folderPath}/{fileName} ({len(fileContent)} bytes)") # Generate filename workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None filename = self._generateMeaningfulFileName( "file_upload_result", "json", workflowContext, "uploadFile" ) result = { "success": True, "siteId": siteId, "filePath": f"{folderPath}/{fileName}", "fileSize": len(fileContent), "uploadResult": uploadResult } validationMetadata = self._createValidationMetadata( "uploadFile", siteId=siteId, filePath=f"{folderPath}/{fileName}", fileSize=len(fileContent) ) document = ActionDocument( documentName=filename, documentData=json.dumps(result, indent=2), mimeType="application/json", validationMetadata=validationMetadata ) return ActionResult.isSuccess(documents=[document]) except Exception as e: errorMsg = f"Error uploading file to SharePoint: {str(e)}" logger.error(errorMsg) return ActionResult.isFailure(error=errorMsg)