chore: ruff format
This commit is contained in:
@@ -88,7 +88,9 @@ class NextcloudClient:
|
|||||||
category: str | None = None,
|
category: str | None = None,
|
||||||
):
|
):
|
||||||
"""Create a new note."""
|
"""Create a new note."""
|
||||||
return await self.notes.create_note(title=title, content=content, category=category)
|
return await self.notes.create_note(
|
||||||
|
title=title, content=content, category=category
|
||||||
|
)
|
||||||
|
|
||||||
async def notes_update_note(
|
async def notes_update_note(
|
||||||
self,
|
self,
|
||||||
@@ -113,7 +115,6 @@ class NextcloudClient:
|
|||||||
all_notes = await self.notes.get_all_notes()
|
all_notes = await self.notes.get_all_notes()
|
||||||
return self._notes_search.search_notes(all_notes, query)
|
return self._notes_search.search_notes(all_notes, query)
|
||||||
|
|
||||||
|
|
||||||
async def notes_delete_note(self, *, note_id: int):
|
async def notes_delete_note(self, *, note_id: int):
|
||||||
"""Delete a note and its attachments."""
|
"""Delete a note and its attachments."""
|
||||||
return await self.notes.delete_note(note_id)
|
return await self.notes.delete_note(note_id)
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ from typing import List, Dict, Any
|
|||||||
class NotesSearchController:
|
class NotesSearchController:
|
||||||
"""Handles notes search logic and scoring."""
|
"""Handles notes search logic and scoring."""
|
||||||
|
|
||||||
def search_notes(self, notes: List[Dict[str, Any]], query: str) -> List[Dict[str, Any]]:
|
def search_notes(
|
||||||
|
self, notes: List[Dict[str, Any]], query: str
|
||||||
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Search notes using token-based matching with relevance ranking.
|
Search notes using token-based matching with relevance ranking.
|
||||||
Returns notes sorted by relevance score.
|
Returns notes sorted by relevance score.
|
||||||
@@ -25,13 +27,15 @@ class NotesSearchController:
|
|||||||
|
|
||||||
# Only include notes with a non-zero score
|
# Only include notes with a non-zero score
|
||||||
if score >= 0.5:
|
if score >= 0.5:
|
||||||
search_results.append({
|
search_results.append(
|
||||||
"id": note.get("id"),
|
{
|
||||||
"title": note.get("title"),
|
"id": note.get("id"),
|
||||||
"category": note.get("category"),
|
"title": note.get("title"),
|
||||||
"modified": note.get("modified"),
|
"category": note.get("category"),
|
||||||
"_score": score, # Include score for sorting
|
"modified": note.get("modified"),
|
||||||
})
|
"_score": score, # Include score for sorting
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Sort by score in descending order
|
# Sort by score in descending order
|
||||||
search_results.sort(key=lambda x: x["_score"], reverse=True)
|
search_results.sort(key=lambda x: x["_score"], reverse=True)
|
||||||
@@ -48,7 +52,9 @@ class NotesSearchController:
|
|||||||
tokens = [token for token in tokens if len(token) > 1]
|
tokens = [token for token in tokens if len(token) > 1]
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
def _process_note_content(self, note: Dict[str, Any]) -> tuple[List[str], List[str]]:
|
def _process_note_content(
|
||||||
|
self, note: Dict[str, Any]
|
||||||
|
) -> tuple[List[str], List[str]]:
|
||||||
"""
|
"""
|
||||||
Tokenize and normalize note title and content.
|
Tokenize and normalize note title and content.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
|
|
||||||
async def get_note(self, note_id: int) -> Dict[str, Any]:
|
async def get_note(self, note_id: int) -> Dict[str, Any]:
|
||||||
"""Get a specific note by ID."""
|
"""Get a specific note by ID."""
|
||||||
response = await self._make_request("GET", f"/apps/notes/api/v1/notes/{note_id}")
|
response = await self._make_request(
|
||||||
|
"GET", f"/apps/notes/api/v1/notes/{note_id}"
|
||||||
|
)
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
async def create_note(
|
async def create_note(
|
||||||
@@ -41,7 +43,9 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
if category:
|
if category:
|
||||||
body["category"] = category
|
body["category"] = category
|
||||||
|
|
||||||
response = await self._make_request("POST", "/apps/notes/api/v1/notes", json=body)
|
response = await self._make_request(
|
||||||
|
"POST", "/apps/notes/api/v1/notes", json=body
|
||||||
|
)
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
async def update(
|
async def update(
|
||||||
@@ -61,7 +65,9 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
old_category = old_note.get("category", "")
|
old_category = old_note.get("category", "")
|
||||||
logger.info(f"Current category for note {note_id}: '{old_category}'")
|
logger.info(f"Current category for note {note_id}: '{old_category}'")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not fetch current note {note_id} details before update: {e}")
|
logger.warning(
|
||||||
|
f"Could not fetch current note {note_id} details before update: {e}"
|
||||||
|
)
|
||||||
old_note = None
|
old_note = None
|
||||||
|
|
||||||
# Prepare update body
|
# Prepare update body
|
||||||
@@ -73,31 +79,43 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
if category:
|
if category:
|
||||||
body["category"] = category
|
body["category"] = category
|
||||||
|
|
||||||
logger.info(f"Attempting to update note {note_id} with etag {etag}. Body: {body}")
|
logger.info(
|
||||||
|
f"Attempting to update note {note_id} with etag {etag}. Body: {body}"
|
||||||
|
)
|
||||||
|
|
||||||
response = await self._make_request(
|
response = await self._make_request(
|
||||||
"PUT",
|
"PUT",
|
||||||
f"/apps/notes/api/v1/notes/{note_id}",
|
f"/apps/notes/api/v1/notes/{note_id}",
|
||||||
json=body,
|
json=body,
|
||||||
headers={"If-Match": f'"{etag}"'}
|
headers={"If-Match": f'"{etag}"'},
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Update response for note {note_id}: Status {response.status_code}")
|
logger.info(
|
||||||
|
f"Update response for note {note_id}: Status {response.status_code}"
|
||||||
|
)
|
||||||
updated_note = response.json()
|
updated_note = response.json()
|
||||||
|
|
||||||
# Check for category change and cleanup old attachment directory if needed
|
# Check for category change and cleanup old attachment directory if needed
|
||||||
if old_note and category is not None and old_note.get("category", "") != category:
|
if (
|
||||||
logger.info(f"Category changed from '{old_note.get('category', '')}' to '{category}' - cleaning up old attachment directory")
|
old_note
|
||||||
|
and category is not None
|
||||||
|
and old_note.get("category", "") != category
|
||||||
|
):
|
||||||
|
logger.info(
|
||||||
|
f"Category changed from '{old_note.get('category', '')}' to '{category}' - cleaning up old attachment directory"
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
# Import here to avoid circular imports
|
# Import here to avoid circular imports
|
||||||
from .webdav_client import WebDAVClient
|
from .webdav_client import WebDAVClient
|
||||||
|
|
||||||
webdav_client = WebDAVClient(self._client, self.username)
|
webdav_client = WebDAVClient(self._client, self.username)
|
||||||
await webdav_client.cleanup_old_attachment_directory(
|
await webdav_client.cleanup_old_attachment_directory(
|
||||||
note_id=note_id,
|
note_id=note_id, old_category=old_note.get("category", "")
|
||||||
old_category=old_note.get("category", "")
|
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error cleaning up old attachment directory for note {note_id}: {e}")
|
logger.error(
|
||||||
|
f"Error cleaning up old attachment directory for note {note_id}: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
return updated_note
|
return updated_note
|
||||||
|
|
||||||
@@ -115,27 +133,36 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
if category != "":
|
if category != "":
|
||||||
potential_categories.append("") # Empty category
|
potential_categories.append("") # Empty category
|
||||||
|
|
||||||
logger.info(f"Note {note_id} has category: '{category}', will check attachment directories in: {potential_categories}")
|
logger.info(
|
||||||
|
f"Note {note_id} has category: '{category}', will check attachment directories in: {potential_categories}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not fetch note {note_id} details before deletion: {e}")
|
logger.warning(
|
||||||
|
f"Could not fetch note {note_id} details before deletion: {e}"
|
||||||
|
)
|
||||||
potential_categories = ["", "Unknown"] # Try common categories
|
potential_categories = ["", "Unknown"] # Try common categories
|
||||||
|
|
||||||
# Delete the note via API
|
# Delete the note via API
|
||||||
logger.info(f"Deleting note {note_id} via API")
|
logger.info(f"Deleting note {note_id} via API")
|
||||||
response = await self._make_request("DELETE", f"/apps/notes/api/v1/notes/{note_id}")
|
response = await self._make_request(
|
||||||
|
"DELETE", f"/apps/notes/api/v1/notes/{note_id}"
|
||||||
|
)
|
||||||
logger.info(f"Note {note_id} deleted successfully via API")
|
logger.info(f"Note {note_id} deleted successfully via API")
|
||||||
json_response = response.json()
|
json_response = response.json()
|
||||||
|
|
||||||
# Clean up attachment directories
|
# Clean up attachment directories
|
||||||
try:
|
try:
|
||||||
from .webdav_client import WebDAVClient
|
from .webdav_client import WebDAVClient
|
||||||
|
|
||||||
webdav_client = WebDAVClient(self._client, self.username)
|
webdav_client = WebDAVClient(self._client, self.username)
|
||||||
|
|
||||||
for cat in potential_categories:
|
for cat in potential_categories:
|
||||||
try:
|
try:
|
||||||
await webdav_client.cleanup_note_attachments(note_id, cat)
|
await webdav_client.cleanup_note_attachments(note_id, cat)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to cleanup attachments for category '{cat}': {e}")
|
logger.warning(
|
||||||
|
f"Failed to cleanup attachments for category '{cat}': {e}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Error during attachment cleanup: {e}")
|
logger.warning(f"Error during attachment cleanup: {e}")
|
||||||
|
|
||||||
@@ -158,7 +185,9 @@ class NotesClient(BaseNextcloudClient):
|
|||||||
else:
|
else:
|
||||||
new_content = content # No separator needed for empty notes
|
new_content = content # No separator needed for empty notes
|
||||||
|
|
||||||
logger.info(f"Combining existing content ({len(existing_content)} chars) with new content ({len(content)} chars)")
|
logger.info(
|
||||||
|
f"Combining existing content ({len(existing_content)} chars) with new content ({len(content)} chars)"
|
||||||
|
)
|
||||||
|
|
||||||
# Update with combined content
|
# Update with combined content
|
||||||
return await self.update(
|
return await self.update(
|
||||||
|
|||||||
@@ -32,17 +32,23 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
propfind_resp = await self._client.request(
|
propfind_resp = await self._client.request(
|
||||||
"PROPFIND", webdav_path, headers=propfind_headers
|
"PROPFIND", webdav_path, headers=propfind_headers
|
||||||
)
|
)
|
||||||
logger.info(f"Resource exists check (PROPFIND) status: {propfind_resp.status_code}")
|
logger.info(
|
||||||
|
f"Resource exists check (PROPFIND) status: {propfind_resp.status_code}"
|
||||||
|
)
|
||||||
except HTTPStatusError as e:
|
except HTTPStatusError as e:
|
||||||
if e.response.status_code == 404:
|
if e.response.status_code == 404:
|
||||||
logger.info(f"Resource '{webdav_path}' doesn't exist, no deletion needed.")
|
logger.info(
|
||||||
|
f"Resource '{webdav_path}' doesn't exist, no deletion needed."
|
||||||
|
)
|
||||||
return {"status_code": 404}
|
return {"status_code": 404}
|
||||||
# For other errors, continue with deletion attempt
|
# For other errors, continue with deletion attempt
|
||||||
|
|
||||||
# Proceed with deletion
|
# Proceed with deletion
|
||||||
response = await self._client.delete(webdav_path, headers=headers)
|
response = await self._client.delete(webdav_path, headers=headers)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
logger.info(f"Successfully deleted WebDAV resource '{webdav_path}' (Status: {response.status_code})")
|
logger.info(
|
||||||
|
f"Successfully deleted WebDAV resource '{webdav_path}' (Status: {response.status_code})"
|
||||||
|
)
|
||||||
return {"status_code": response.status_code}
|
return {"status_code": response.status_code}
|
||||||
|
|
||||||
except HTTPStatusError as e:
|
except HTTPStatusError as e:
|
||||||
@@ -53,13 +59,19 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
logger.info(f"Resource '{webdav_path}' not found, no deletion needed.")
|
logger.info(f"Resource '{webdav_path}' not found, no deletion needed.")
|
||||||
return {"status_code": 404}
|
return {"status_code": 404}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Unexpected error deleting WebDAV resource '{webdav_path}': {e}")
|
logger.warning(
|
||||||
|
f"Unexpected error deleting WebDAV resource '{webdav_path}': {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
async def cleanup_old_attachment_directory(self, note_id: int, old_category: str) -> Dict[str, Any]:
|
async def cleanup_old_attachment_directory(
|
||||||
|
self, note_id: int, old_category: str
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""Clean up the attachment directory for a note in its old category location."""
|
"""Clean up the attachment directory for a note in its old category location."""
|
||||||
old_category_path_part = f"{old_category}/" if old_category else ""
|
old_category_path_part = f"{old_category}/" if old_category else ""
|
||||||
old_attachment_dir_path = f"Notes/{old_category_path_part}.attachments.{note_id}/"
|
old_attachment_dir_path = (
|
||||||
|
f"Notes/{old_category_path_part}.attachments.{note_id}/"
|
||||||
|
)
|
||||||
|
|
||||||
logger.info(f"Cleaning up old attachment directory: {old_attachment_dir_path}")
|
logger.info(f"Cleaning up old attachment directory: {old_attachment_dir_path}")
|
||||||
try:
|
try:
|
||||||
@@ -70,18 +82,26 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
logger.error(f"Error during cleanup of old attachment directory: {e}")
|
logger.error(f"Error during cleanup of old attachment directory: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
async def cleanup_note_attachments(self, note_id: int, category: str) -> Dict[str, Any]:
|
async def cleanup_note_attachments(
|
||||||
|
self, note_id: int, category: str
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""Clean up attachment directory for a specific note and category."""
|
"""Clean up attachment directory for a specific note and category."""
|
||||||
cat_path_part = f"{category}/" if category else ""
|
cat_path_part = f"{category}/" if category else ""
|
||||||
attachment_dir_path = f"Notes/{cat_path_part}.attachments.{note_id}/"
|
attachment_dir_path = f"Notes/{cat_path_part}.attachments.{note_id}/"
|
||||||
|
|
||||||
logger.info(f"Attempting to delete attachment directory for note {note_id} in category '{category}' via WebDAV: {attachment_dir_path}")
|
logger.info(
|
||||||
|
f"Attempting to delete attachment directory for note {note_id} in category '{category}' via WebDAV: {attachment_dir_path}"
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
delete_result = await self.delete_resource(path=attachment_dir_path)
|
delete_result = await self.delete_resource(path=attachment_dir_path)
|
||||||
logger.info(f"WebDAV deletion for category '{category}' attachment directory: {delete_result}")
|
logger.info(
|
||||||
|
f"WebDAV deletion for category '{category}' attachment directory: {delete_result}"
|
||||||
|
)
|
||||||
return delete_result
|
return delete_result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed during WebDAV deletion for category '{category}' attachment directory: {e}")
|
logger.warning(
|
||||||
|
f"Failed during WebDAV deletion for category '{category}' attachment directory: {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
async def add_note_attachment(
|
async def add_note_attachment(
|
||||||
@@ -97,14 +117,20 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
webdav_base = self._get_webdav_base_path()
|
webdav_base = self._get_webdav_base_path()
|
||||||
category_path_part = f"{category}/" if category else ""
|
category_path_part = f"{category}/" if category else ""
|
||||||
attachment_dir_segment = f".attachments.{note_id}"
|
attachment_dir_segment = f".attachments.{note_id}"
|
||||||
parent_dir_webdav_rel_path = f"Notes/{category_path_part}{attachment_dir_segment}"
|
parent_dir_webdav_rel_path = (
|
||||||
|
f"Notes/{category_path_part}{attachment_dir_segment}"
|
||||||
|
)
|
||||||
parent_dir_path = f"{webdav_base}/{parent_dir_webdav_rel_path}"
|
parent_dir_path = f"{webdav_base}/{parent_dir_webdav_rel_path}"
|
||||||
attachment_path = f"{parent_dir_path}/{filename}"
|
attachment_path = f"{parent_dir_path}/{filename}"
|
||||||
|
|
||||||
logger.info(f"Uploading attachment for note {note_id} (category: '{category or ''}') to WebDAV path: {attachment_path}")
|
logger.info(
|
||||||
|
f"Uploading attachment for note {note_id} (category: '{category or ''}') to WebDAV path: {attachment_path}"
|
||||||
|
)
|
||||||
|
|
||||||
# Log current auth settings
|
# Log current auth settings
|
||||||
logger.info(f"WebDAV auth settings - Username: {self.username}, Auth Type: {type(self._client.auth).__name__}")
|
logger.info(
|
||||||
|
f"WebDAV auth settings - Username: {self.username}, Auth Type: {type(self._client.auth).__name__}"
|
||||||
|
)
|
||||||
|
|
||||||
if not mime_type:
|
if not mime_type:
|
||||||
mime_type, _ = mimetypes.guess_type(filename)
|
mime_type, _ = mimetypes.guess_type(filename)
|
||||||
@@ -123,42 +149,62 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if notes_dir_response.status_code == 401:
|
if notes_dir_response.status_code == 401:
|
||||||
logger.error("WebDAV authentication failed for Notes directory. Please verify WebDAV permissions.")
|
logger.error(
|
||||||
|
"WebDAV authentication failed for Notes directory. Please verify WebDAV permissions."
|
||||||
|
)
|
||||||
raise HTTPStatusError(
|
raise HTTPStatusError(
|
||||||
f"Authentication error accessing WebDAV Notes directory: {notes_dir_response.status_code}",
|
f"Authentication error accessing WebDAV Notes directory: {notes_dir_response.status_code}",
|
||||||
request=notes_dir_response.request,
|
request=notes_dir_response.request,
|
||||||
response=notes_dir_response,
|
response=notes_dir_response,
|
||||||
)
|
)
|
||||||
elif notes_dir_response.status_code >= 400:
|
elif notes_dir_response.status_code >= 400:
|
||||||
logger.error(f"Error accessing WebDAV Notes directory: {notes_dir_response.status_code}")
|
logger.error(
|
||||||
|
f"Error accessing WebDAV Notes directory: {notes_dir_response.status_code}"
|
||||||
|
)
|
||||||
notes_dir_response.raise_for_status()
|
notes_dir_response.raise_for_status()
|
||||||
else:
|
else:
|
||||||
logger.info(f"Successfully accessed WebDAV Notes directory (Status: {notes_dir_response.status_code})")
|
logger.info(
|
||||||
|
f"Successfully accessed WebDAV Notes directory (Status: {notes_dir_response.status_code})"
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure the parent directory exists using MKCOL
|
# Ensure the parent directory exists using MKCOL
|
||||||
logger.info(f"Ensuring attachments directory exists: {parent_dir_path}")
|
logger.info(f"Ensuring attachments directory exists: {parent_dir_path}")
|
||||||
mkcol_headers = {"OCS-APIRequest": "true"}
|
mkcol_headers = {"OCS-APIRequest": "true"}
|
||||||
mkcol_response = await self._client.request("MKCOL", parent_dir_path, headers=mkcol_headers)
|
mkcol_response = await self._client.request(
|
||||||
|
"MKCOL", parent_dir_path, headers=mkcol_headers
|
||||||
|
)
|
||||||
|
|
||||||
# MKCOL should return 201 Created or 405 Method Not Allowed (if directory already exists)
|
# MKCOL should return 201 Created or 405 Method Not Allowed (if directory already exists)
|
||||||
if mkcol_response.status_code not in [201, 405]:
|
if mkcol_response.status_code not in [201, 405]:
|
||||||
logger.warning(f"Unexpected status code {mkcol_response.status_code} when creating attachments directory")
|
logger.warning(
|
||||||
|
f"Unexpected status code {mkcol_response.status_code} when creating attachments directory"
|
||||||
|
)
|
||||||
mkcol_response.raise_for_status()
|
mkcol_response.raise_for_status()
|
||||||
else:
|
else:
|
||||||
logger.info(f"Created/verified directory: {parent_dir_path} (Status: {mkcol_response.status_code})")
|
logger.info(
|
||||||
|
f"Created/verified directory: {parent_dir_path} (Status: {mkcol_response.status_code})"
|
||||||
|
)
|
||||||
|
|
||||||
# Proceed with the PUT request
|
# Proceed with the PUT request
|
||||||
logger.info(f"Putting attachment file to: {attachment_path}")
|
logger.info(f"Putting attachment file to: {attachment_path}")
|
||||||
response = await self._client.put(attachment_path, content=content, headers=headers)
|
response = await self._client.put(
|
||||||
|
attachment_path, content=content, headers=headers
|
||||||
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
logger.info(f"Successfully uploaded attachment '{filename}' to note {note_id} (Status: {response.status_code})")
|
logger.info(
|
||||||
|
f"Successfully uploaded attachment '{filename}' to note {note_id} (Status: {response.status_code})"
|
||||||
|
)
|
||||||
return {"status_code": response.status_code}
|
return {"status_code": response.status_code}
|
||||||
|
|
||||||
except HTTPStatusError as e:
|
except HTTPStatusError as e:
|
||||||
logger.error(f"HTTP error uploading attachment '{filename}' to note {note_id}: {e}")
|
logger.error(
|
||||||
|
f"HTTP error uploading attachment '{filename}' to note {note_id}: {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unexpected error uploading attachment '{filename}' to note {note_id}: {e}")
|
logger.error(
|
||||||
|
f"Unexpected error uploading attachment '{filename}' to note {note_id}: {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
async def get_note_attachment(
|
async def get_note_attachment(
|
||||||
@@ -170,7 +216,9 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
attachment_dir_segment = f".attachments.{note_id}"
|
attachment_dir_segment = f".attachments.{note_id}"
|
||||||
attachment_path = f"{webdav_base}/Notes/{category_path_part}{attachment_dir_segment}/{filename}"
|
attachment_path = f"{webdav_base}/Notes/{category_path_part}{attachment_dir_segment}/{filename}"
|
||||||
|
|
||||||
logger.info(f"Fetching attachment for note {note_id} (category: '{category or ''}') from WebDAV path: {attachment_path}")
|
logger.info(
|
||||||
|
f"Fetching attachment for note {note_id} (category: '{category or ''}') from WebDAV path: {attachment_path}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await self._client.get(attachment_path)
|
response = await self._client.get(attachment_path)
|
||||||
@@ -179,12 +227,18 @@ class WebDAVClient(BaseNextcloudClient):
|
|||||||
content = response.content
|
content = response.content
|
||||||
mime_type = response.headers.get("content-type", "application/octet-stream")
|
mime_type = response.headers.get("content-type", "application/octet-stream")
|
||||||
|
|
||||||
logger.info(f"Successfully fetched attachment '{filename}' ({mime_type}, {len(content)} bytes)")
|
logger.info(
|
||||||
|
f"Successfully fetched attachment '{filename}' ({mime_type}, {len(content)} bytes)"
|
||||||
|
)
|
||||||
return content, mime_type
|
return content, mime_type
|
||||||
|
|
||||||
except HTTPStatusError as e:
|
except HTTPStatusError as e:
|
||||||
logger.error(f"HTTP error fetching attachment '{filename}' for note {note_id}: {e}")
|
logger.error(
|
||||||
|
f"HTTP error fetching attachment '{filename}' for note {note_id}: {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unexpected error fetching attachment '{filename}' for note {note_id}: {e}")
|
logger.error(
|
||||||
|
f"Unexpected error fetching attachment '{filename}' for note {note_id}: {e}"
|
||||||
|
)
|
||||||
raise e
|
raise e
|
||||||
|
|||||||
Reference in New Issue
Block a user