""" SharePoint method module. Handles SharePoint operations using the SharePoint service. """ import logging from typing import Dict, Any, List, Optional from datetime import datetime, UTC import json from modules.methods.methodBase import MethodBase, ActionResult, action logger = logging.getLogger(__name__) class SharepointService: """Service for Microsoft SharePoint operations using Graph API""" def __init__(self, serviceContainer: Any): self.serviceContainer = serviceContainer def _getMicrosoftConnection(self, connectionReference: str) -> Optional[Dict[str, Any]]: """Get Microsoft connection from connection reference""" try: userConnection = self.serviceContainer.getUserConnectionFromConnectionReference(connectionReference) if userConnection and userConnection.authority == "microsoft" and userConnection.enabled: return { "id": userConnection.id, "accessToken": userConnection.accessToken, "refreshToken": userConnection.refreshToken, "scopes": userConnection.scopes } return None except Exception as e: logger.error(f"Error getting Microsoft connection: {str(e)}") return None async def searchContent(self, connectionReference: str, query: str, siteId: str = None, contentType: str = None, maxResults: int = 10) -> Dict[str, Any]: """Search SharePoint content using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "connectionReference": connectionReference } # For now, simulate SharePoint search # In a real implementation, you would use Microsoft Graph API search_prompt = f""" Search SharePoint content for the following query. Query: {query} Site ID: {siteId or 'All sites'} Content Type: {contentType or 'All types'} Max Results: {maxResults} Please provide: 1. Relevant search results 2. Content summaries 3. File and document information 4. Site and list references 5. Metadata and properties """ # Use AI to simulate search results search_results = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(search_prompt) return { "query": query, "siteId": siteId, "contentType": contentType, "maxResults": maxResults, "results": search_results, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error searching SharePoint: {str(e)}") return { "error": str(e) } async def readItem(self, connectionReference: str, itemId: str, siteId: str = None, listId: str = None) -> Dict[str, Any]: """Read SharePoint item using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "itemId": itemId, "connectionReference": connectionReference } # For now, simulate item reading # In a real implementation, you would use Microsoft Graph API read_prompt = f""" Read SharePoint item details. Item ID: {itemId} Site ID: {siteId or 'Default site'} List ID: {listId or 'Default list'} Please provide: 1. Item properties and metadata 2. Content and attachments 3. Permissions and access rights 4. Version history if available 5. Related items and links """ # Use AI to simulate item data item_data = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(read_prompt) return { "itemId": itemId, "siteId": siteId, "listId": listId, "data": item_data, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error reading SharePoint item: {str(e)}") return { "error": str(e), "itemId": itemId } async def writeItem(self, connectionReference: str, siteId: str, listId: str, item: Dict[str, Any]) -> Dict[str, Any]: """Write SharePoint item using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "connectionReference": connectionReference } # For now, simulate item writing # In a real implementation, you would use Microsoft Graph API write_prompt = f""" Write item to SharePoint list. Site ID: {siteId} List ID: {listId} Item data: {json.dumps(item, indent=2)} Please provide: 1. Item creation/update details 2. Validation and formatting 3. Permission settings 4. Workflow triggers if applicable 5. Success confirmation """ # Use AI to simulate item creation write_result = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(write_prompt) return { "siteId": siteId, "listId": listId, "item": item, "result": write_result, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error writing SharePoint item: {str(e)}") return { "error": str(e) } async def readList(self, connectionReference: str, listId: str, siteId: str = None, query: str = None, maxResults: int = 10) -> Dict[str, Any]: """Read SharePoint list using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "listId": listId, "connectionReference": connectionReference } # For now, simulate list reading # In a real implementation, you would use Microsoft Graph API list_prompt = f""" Read SharePoint list items. List ID: {listId} Site ID: {siteId or 'Default site'} Query: {query or 'All items'} Max Results: {maxResults} Please provide: 1. List structure and columns 2. Item data and properties 3. Sorting and filtering options 4. Pagination information 5. List metadata and settings """ # Use AI to simulate list data list_data = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(list_prompt) return { "listId": listId, "siteId": siteId, "query": query, "maxResults": maxResults, "data": list_data, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error reading SharePoint list: {str(e)}") return { "error": str(e), "listId": listId } async def writeList(self, connectionReference: str, siteId: str, listId: str, items: List[Dict[str, Any]]) -> Dict[str, Any]: """Write multiple items to SharePoint list using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "connectionReference": connectionReference } # For now, simulate bulk writing # In a real implementation, you would use Microsoft Graph API bulk_prompt = f""" Write multiple items to SharePoint list. Site ID: {siteId} List ID: {listId} Number of items: {len(items)} Items data: {json.dumps(items[:3], indent=2)} # Show first 3 items Please provide: 1. Bulk operation details 2. Validation and error handling 3. Performance optimization 4. Success/failure status for each item 5. Batch processing results """ # Use AI to simulate bulk operation bulk_result = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(bulk_prompt) return { "siteId": siteId, "listId": listId, "items": items, "result": bulk_result, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error writing to SharePoint list: {str(e)}") return { "error": str(e) } async def createList(self, connectionReference: str, siteId: str, name: str, description: str = None, template: str = "genericList", fields: List[Dict[str, Any]] = None) -> Dict[str, Any]: """Create SharePoint list using Microsoft Graph API""" try: connection = self._getMicrosoftConnection(connectionReference) if not connection: return { "error": "No valid Microsoft connection found for the provided connection reference", "connectionReference": connectionReference } # For now, simulate list creation # In a real implementation, you would use Microsoft Graph API create_prompt = f""" Create a new SharePoint list. Site ID: {siteId} Name: {name} Description: {description or 'No description'} Template: {template} Fields: {json.dumps(fields, indent=2) if fields else 'Default fields'} Please provide: 1. List structure and configuration 2. Column definitions and types 3. Default views and permissions 4. Workflow and automation settings 5. Creation confirmation and next steps """ # Use AI to simulate list creation creation_result = await self.serviceContainer.interfaceAiCalls.callAiTextAdvanced(create_prompt) return { "siteId": siteId, "name": name, "description": description, "template": template, "fields": fields, "result": creation_result, "connection": { "id": connection["id"], "authority": "microsoft", "reference": connectionReference } } except Exception as e: logger.error(f"Error creating SharePoint list: {str(e)}") return { "error": str(e) } class MethodSharepoint(MethodBase): """SharePoint method implementation for site operations""" def __init__(self, serviceContainer: Any): """Initialize the SharePoint method""" super().__init__(serviceContainer) self.name = "sharepoint" self.description = "Handle SharePoint site operations like reading and writing lists" self.sharepointService = SharepointService(serviceContainer) @action async def search(self, parameters: Dict[str, Any]) -> ActionResult: """Search SharePoint content""" try: connectionReference = parameters.get("connectionReference") query = parameters.get("query") siteId = parameters.get("siteId") contentType = parameters.get("contentType") maxResults = parameters.get("maxResults", 10) if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not query: return self._createResult( success=False, data={}, error="Search query is required" ) # Search content results = await self.sharepointService.searchContent( connectionReference=connectionReference, query=query, siteId=siteId, contentType=contentType, maxResults=maxResults ) return self._createResult( success=True, data=results ) except Exception as e: logger.error(f"Error searching SharePoint: {str(e)}") return self._createResult( success=False, data={}, error=str(e) ) @action async def read(self, parameters: Dict[str, Any]) -> ActionResult: """Read SharePoint item""" try: connectionReference = parameters.get("connectionReference") itemId = parameters.get("itemId") siteId = parameters.get("siteId") listId = parameters.get("listId") if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not itemId: return self._createResult( success=False, data={}, error="Item ID is required" ) # Read item item = await self.sharepointService.readItem( connectionReference=connectionReference, itemId=itemId, siteId=siteId, listId=listId ) return self._createResult( success=True, data=item ) except Exception as e: logger.error(f"Error reading SharePoint item: {str(e)}") return self._createResult( success=False, data={}, error=str(e) ) @action async def write(self, parameters: Dict[str, Any]) -> ActionResult: """Write SharePoint item""" try: connectionReference = parameters.get("connectionReference") siteId = parameters.get("siteId") listId = parameters.get("listId") item = parameters.get("item", {}) if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not siteId or not listId: return self._createResult( success=False, data={}, error="Site ID and list ID are required" ) # Write item result = await self.sharepointService.writeItem( connectionReference=connectionReference, siteId=siteId, listId=listId, item=item ) return self._createResult( success=True, data=result ) except Exception as e: logger.error(f"Error writing SharePoint item: {str(e)}") return self._createResult( success=False, data={}, error=str(e) ) @action async def readList(self, parameters: Dict[str, Any]) -> ActionResult: """Read SharePoint list""" try: connectionReference = parameters.get("connectionReference") listId = parameters.get("listId") siteId = parameters.get("siteId") query = parameters.get("query") maxResults = parameters.get("maxResults", 10) if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not listId: return self._createResult( success=False, data={}, error="List ID is required" ) # Read list items = await self.sharepointService.readList( connectionReference=connectionReference, listId=listId, siteId=siteId, query=query, maxResults=maxResults ) return self._createResult( success=True, data=items ) except Exception as e: logger.error(f"Error reading SharePoint list: {str(e)}") return self._createResult( success=False, data={}, error=str(e) ) @action async def writeList(self, parameters: Dict[str, Any]) -> ActionResult: """Write multiple items to SharePoint list""" try: connectionReference = parameters.get("connectionReference") siteId = parameters.get("siteId") listId = parameters.get("listId") items = parameters.get("items", []) if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not siteId or not listId: return self._createResult( success=False, data={}, error="Site ID and list ID are required" ) # Write items result = await self.sharepointService.writeList( connectionReference=connectionReference, siteId=siteId, listId=listId, items=items ) return self._createResult( success=True, data=result ) except Exception as e: logger.error(f"Error writing to SharePoint list: {str(e)}") return self._createResult( success=False, data={}, error=str(e) ) @action async def createList(self, parameters: Dict[str, Any]) -> ActionResult: """Create SharePoint list""" try: connectionReference = parameters.get("connectionReference") siteId = parameters.get("siteId") name = parameters.get("name") description = parameters.get("description") template = parameters.get("template", "genericList") fields = parameters.get("fields", []) if not connectionReference: return self._createResult( success=False, data={}, error="Connection reference is required" ) if not siteId or not name: return self._createResult( success=False, data={}, error="Site ID and list name are required" ) # Create list list = await self.sharepointService.createList( connectionReference=connectionReference, siteId=siteId, name=name, description=description, template=template, fields=fields ) return self._createResult( success=True, data=list ) except Exception as e: logger.error(f"Error creating SharePoint list: {str(e)}") return self._createResult( success=False, data={}, error=str(e) )