|
1 | 1 | # SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors |
2 | 2 | # SPDX-License-Identifier: AGPL-3.0-or-later |
| 3 | +from functools import lru_cache |
| 4 | + |
| 5 | +import niquests |
3 | 6 | from langchain_core.tools import tool |
4 | 7 | from nc_py_api import AsyncNextcloudApp |
5 | | -import niquests |
| 8 | +from nc_py_api.files.files_async import AsyncFilesAPI, FsNode |
6 | 9 |
|
| 10 | +from ex_app.lib.all_tools.lib.decorator import dangerous_tool, safe_tool |
7 | 11 | from ex_app.lib.all_tools.lib.files import get_file_id_from_file_url |
8 | 12 |
|
9 | | -from ex_app.lib.all_tools.lib.decorator import safe_tool, dangerous_tool |
10 | | - |
11 | 13 |
|
12 | 14 | async def get_tools(nc: AsyncNextcloudApp): |
13 | 15 |
|
@@ -50,16 +52,59 @@ async def get_file_content_by_file_link(file_url: str): |
50 | 52 |
|
51 | 53 | return response.text |
52 | 54 |
|
| 55 | + def __format_fs_node(fsnode: FsNode) -> dict: |
| 56 | + # todo: permissions info |
| 57 | + return { |
| 58 | + 'path': fsnode.user_path, |
| 59 | + 'file_id': fsnode.info.fileid, |
| 60 | + 'etag': fsnode.etag.replace('"', '').replace("'", ''), |
| 61 | + 'bytes': fsnode.info.size, |
| 62 | + 'creation_date': fsnode.info.creation_date.isoformat(), |
| 63 | + 'last_modified': fsnode.info.last_modified.isoformat(), |
| 64 | + 'mimetype': fsnode.info.mimetype, |
| 65 | + 'is_shared': fsnode.is_shared, |
| 66 | + 'is_favourite': fsnode.info.favorite, |
| 67 | + 'is_version': fsnode.info.is_version, |
| 68 | + 'trash_info': { |
| 69 | + 'in_trash': fsnode.info.in_trash, |
| 70 | + **({ |
| 71 | + 'trashbin_filename': fsnode.info.trashbin_filename, |
| 72 | + 'original_location': fsnode.info.trashbin_original_location, |
| 73 | + 'deletion_time': fsnode.info.trashbin_deletion_time, |
| 74 | + } if fsnode.info.in_trash else {}), |
| 75 | + }, |
| 76 | + 'lock_info': { |
| 77 | + 'is_locked': fsnode.lock_info.is_locked, |
| 78 | + **({ |
| 79 | + 'owner': fsnode.lock_info.owner, |
| 80 | + 'owner_display_name': fsnode.lock_info.owner_display_name, |
| 81 | + 'type': fsnode.lock_info.type.name, |
| 82 | + 'creation_time': fsnode.lock_info.lock_creation_time, |
| 83 | + 'ttl': fsnode.lock_info.lock_ttl, |
| 84 | + 'locked_by_app': fsnode.lock_info.owner_editor, |
| 85 | + } if fsnode.lock_info.is_locked else {}), |
| 86 | + }, |
| 87 | + } |
| 88 | + |
| 89 | + |
53 | 90 | @tool |
54 | 91 | @safe_tool |
55 | | - async def get_folder_tree(depth: int): |
| 92 | + async def get_file_tree(path: str = '/', include_metadata = False, depth: int = 1): |
56 | 93 | """ |
57 | | - Get the folder tree of the user (lists the files the user has in Nextcloud Files) |
58 | | - :param depth: the depth of the returned folder tree |
| 94 | + Get the file tree of the user (lists the files the user has in Nextcloud Files) |
| 95 | + :param path: the path to enumerate. It should start directly with the folder name from at the root like /Media and NOT /userid/files/Media |
| 96 | + :param include_metadata: include the etag, file/folder id, last modified times, etc. with the file/folder paths |
| 97 | + :param depth: how many directory levels should be included in output. Default = 1 (only specified directory). Max depth = 5. |
59 | 98 | :return: |
60 | 99 | """ |
61 | 100 |
|
62 | | - return await nc.ocs('GET', '/ocs/v2.php/apps/files/api/v1/folder-tree', params={'depth': depth}, response_type='json') |
| 101 | + files_handle = AsyncFilesAPI(nc._session) |
| 102 | + fsnode_list = await files_handle.listdir(path, min(5, depth)) |
| 103 | + if include_metadata: |
| 104 | + return [__format_fs_node(fsnode) for fsnode in fsnode_list] |
| 105 | + |
| 106 | + return [fsnode.user_path for fsnode in fsnode_list] |
| 107 | + |
63 | 108 |
|
64 | 109 | @tool |
65 | 110 | @dangerous_tool |
@@ -163,7 +208,7 @@ async def delete_file(path: str): |
163 | 208 | return [ |
164 | 209 | get_file_content, |
165 | 210 | get_file_content_by_file_link, |
166 | | - get_folder_tree, |
| 211 | + get_file_tree, |
167 | 212 | create_public_sharing_link, |
168 | 213 | upload_file, |
169 | 214 | create_folder, |
|
0 commit comments