gateway/modules/methods/methodSharepoint.py
2025-06-10 01:25:32 +02:00

217 lines
No EOL
8.9 KiB
Python

from typing import Dict, Any, Optional
import logging
from datetime import datetime, UTC
from office365.runtime.auth.user_credential import UserCredential
from office365.sharepoint.client_context import ClientContext
from office365.sharepoint.files.file import File
from office365.sharepoint.lists.list import List
from office365.sharepoint.lists.list_creation_information import ListCreationInformation
from modules.methods.methodBase import MethodBase, AuthSource, MethodResult
from modules.models.userConnection import UserConnection
logger = logging.getLogger(__name__)
class MethodSharepoint(MethodBase):
"""SharePoint method implementation for document operations"""
def __init__(self):
super().__init__()
self.name = "sharepoint"
self.description = "Handle SharePoint document operations like search, read, and write"
self.auth_source = AuthSource.MICROSOFT
@property
def actions(self) -> Dict[str, Dict[str, Any]]:
"""Available actions and their parameters"""
return {
"search": {
"description": "Search SharePoint documents",
"retryMax": 3,
"timeout": 30,
"parameters": {
"query": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True},
"listName": {"type": "string", "required": False},
"maxResults": {"type": "number", "required": False}
}
},
"read": {
"description": "Read SharePoint document content",
"retryMax": 2,
"timeout": 30,
"parameters": {
"fileUrl": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True}
}
},
"write": {
"description": "Write content to SharePoint document",
"retryMax": 2,
"timeout": 30,
"parameters": {
"fileUrl": {"type": "string", "required": True},
"siteUrl": {"type": "string", "required": True},
"content": {"type": "string", "required": True},
"contentType": {"type": "string", "required": False}
}
}
}
async def execute(self, action: str, parameters: Dict[str, Any], auth_data: Optional[Dict[str, Any]] = None) -> MethodResult:
"""Execute SharePoint method"""
try:
# Validate parameters
if not await self.validate_parameters(action, parameters):
return self._create_result(
success=False,
data={"error": f"Invalid parameters for {action}"}
)
# Get UserConnection from auth_data
if not auth_data or "userConnection" not in auth_data:
return self._create_result(
success=False,
data={"error": "UserConnection required for SharePoint operations"}
)
user_connection: UserConnection = auth_data["userConnection"]
# Execute action
if action == "search":
return await self._search_documents(parameters, user_connection)
elif action == "read":
return await self._read_document(parameters, user_connection)
elif action == "write":
return await self._write_document(parameters, user_connection)
else:
return self._create_result(
success=False,
data={"error": f"Unknown action: {action}"}
)
except Exception as e:
logger.error(f"Error executing SharePoint {action}: {e}")
return self._create_result(
success=False,
data={"error": str(e)}
)
async def _search_documents(self, parameters: Dict[str, Any], user_connection: UserConnection) -> MethodResult:
"""Search SharePoint documents"""
try:
site_url = parameters["siteUrl"]
query = parameters["query"]
list_name = parameters.get("listName")
max_results = parameters.get("maxResults", 10)
# Create SharePoint context
ctx = ClientContext(site_url).with_credentials(
UserCredential(user_connection.authToken, user_connection.refreshToken)
)
# Search in specific list or entire site
if list_name:
target_list = ctx.web.lists.get_by_title(list_name)
items = target_list.items.filter(f"Title eq '{query}'").top(max_results).get().execute_query()
results = [{
"title": item.properties["Title"],
"url": item.properties["FileRef"],
"modified": item.properties["Modified"],
"created": item.properties["Created"]
} for item in items]
else:
# Search entire site
search_results = ctx.search(query).execute_query()
results = [{
"title": result.properties["Title"],
"url": result.properties["Path"],
"modified": result.properties["LastModifiedTime"],
"created": result.properties["Created"]
} for result in search_results[:max_results]]
return self._create_result(
success=True,
data={
"query": query,
"results": results
}
)
except Exception as e:
logger.error(f"Error searching SharePoint documents: {e}")
return self._create_result(
success=False,
data={"error": f"Search failed: {str(e)}"}
)
async def _read_document(self, parameters: Dict[str, Any], user_connection: UserConnection) -> MethodResult:
"""Read SharePoint document content"""
try:
site_url = parameters["siteUrl"]
file_url = parameters["fileUrl"]
# Create SharePoint context
ctx = ClientContext(site_url).with_credentials(
UserCredential(user_connection.authToken, user_connection.refreshToken)
)
# Get file
file = ctx.web.get_file_by_server_relative_url(file_url)
file_content = file.read().execute_query()
return self._create_result(
success=True,
data={
"url": file_url,
"content": file_content.content.decode('utf-8'),
"modified": file.properties["TimeLastModified"],
"size": file.properties["Length"]
}
)
except Exception as e:
logger.error(f"Error reading SharePoint document: {e}")
return self._create_result(
success=False,
data={"error": f"Read failed: {str(e)}"}
)
async def _write_document(self, parameters: Dict[str, Any], user_connection: UserConnection) -> MethodResult:
"""Write content to SharePoint document"""
try:
site_url = parameters["siteUrl"]
file_url = parameters["fileUrl"]
content = parameters["content"]
content_type = parameters.get("contentType", "text/plain")
# Create SharePoint context
ctx = ClientContext(site_url).with_credentials(
UserCredential(user_connection.authToken, user_connection.refreshToken)
)
# Get or create file
try:
file = ctx.web.get_file_by_server_relative_url(file_url)
except:
# Create new file
folder_url = "/".join(file_url.split("/")[:-1])
file_name = file_url.split("/")[-1]
folder = ctx.web.get_folder_by_server_relative_url(folder_url)
file = folder.upload_file(file_name, content.encode('utf-8')).execute_query()
# Update file content
file.write(content.encode('utf-8')).execute_query()
return self._create_result(
success=True,
data={
"url": file_url,
"modified": datetime.now(UTC).isoformat(),
"size": len(content.encode('utf-8'))
}
)
except Exception as e:
logger.error(f"Error writing SharePoint document: {e}")
return self._create_result(
success=False,
data={"error": f"Write failed: {str(e)}"}
)