Skip to content

Commit bedbdd8

Browse files
authored
UiActionFileInfo: added to_fs_node method. (#85)
```python3 def convert_video_to_gif(input_file: FsNode, nc: NextcloudApp): save_path = path.splitext(input_file.user_path)[0] + ".gif" pass @APP.post("/video_to_gif") async def video_to_gif( file: UiFileActionHandlerInfo, nc: Annotated[NextcloudApp, Depends(nc_app)], background_tasks: BackgroundTasks, ): background_tasks.add_task(convert_video_to_gif, file.actionFile.to_fs_node(), nc) return Response() ``` Allowing to create ``FsNode`` from ``UiFileActionHandlerInfo``. Signed-off-by: Alexander Piskun <[email protected]>
1 parent 1726541 commit bedbdd8

File tree

12 files changed

+160
-60
lines changed

12 files changed

+160
-60
lines changed

docs/reference/Files/Files.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ All File APIs are designed to work relative to the current user.
1414

1515
.. autoclass:: nc_py_api.files.FsNode
1616
:members:
17+
18+
.. autoclass:: nc_py_api.files.FilePermissions
19+
:members:

docs/reference/Files/Shares.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,5 @@ Refer to the `Sharing examples <https://github.com/cloud-py-api/nc_py_api/tree/m
1010
.. autoclass:: nc_py_api.files.sharing.Share
1111
:members:
1212

13-
.. autoclass:: nc_py_api.files.sharing.SharePermissions
14-
:members:
15-
1613
.. autoclass:: nc_py_api.files.sharing.ShareType
1714
:members:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nc_py_api[app]>=0.0.30
1+
nc_py_api[app]>=0.0.31

examples/as_app/to_gif/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ run27:
4444
.PHONY: manual_register
4545
manual_register:
4646
docker exec master-nextcloud-1 sudo -u www-data php occ app_ecosystem_v2:app:register to_gif manual_install --json-info \
47-
"{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9030,\"scopes\":{\"required\":[10],\"optional\":[32]},\"protocol\":\"http\",\"system_app\":0}" \
47+
"{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"host\":\"host.docker.internal\",\"port\":9031,\"scopes\":{\"required\":[10],\"optional\":[32]},\"protocol\":\"http\",\"system_app\":0}" \
4848
-e --force-scopes

examples/as_app/to_gif/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
nc_py_api[app]>=0.0.30
1+
nc_py_api[app]>=0.0.31
22
pygifsicle
33
imageio
44
opencv-python

examples/as_app/to_gif/src/main.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
from pygifsicle import optimize
1212
from requests import Response
1313

14-
from nc_py_api import NextcloudApp
14+
from nc_py_api import FsNode, NextcloudApp
1515
from nc_py_api.ex_app import (
1616
LogLvl,
17-
UiActionFileInfo,
1817
UiFileActionHandlerInfo,
1918
nc_app,
2019
run_app,
@@ -24,13 +23,12 @@
2423
APP = FastAPI()
2524

2625

27-
def convert_video_to_gif(input_params: UiActionFileInfo, nc: NextcloudApp):
28-
source_path = path.join(input_params.directory, input_params.name)
29-
save_path = path.splitext(source_path)[0] + ".gif"
30-
nc.log(LogLvl.WARNING, f"Processing:{source_path} -> {save_path}")
26+
def convert_video_to_gif(input_file: FsNode, nc: NextcloudApp):
27+
save_path = path.splitext(input_file.user_path)[0] + ".gif"
28+
nc.log(LogLvl.WARNING, f"Processing:{input_file.user_path} -> {save_path}")
3129
try:
3230
with tempfile.NamedTemporaryFile(mode="w+b") as tmp_in:
33-
nc.files.download2stream(source_path, tmp_in)
31+
nc.files.download2stream(input_file, tmp_in)
3432
nc.log(LogLvl.WARNING, "File downloaded")
3533
tmp_in.flush()
3634
cap = cv2.VideoCapture(tmp_in.name)
@@ -61,7 +59,7 @@ def convert_video_to_gif(input_params: UiActionFileInfo, nc: NextcloudApp):
6159
nc.log(LogLvl.WARNING, "GIF is ready")
6260
nc.files.upload_stream(save_path, tmp_out)
6361
nc.log(LogLvl.WARNING, "Result uploaded")
64-
nc.users.notifications.create(f"{input_params.name} finished!", f"{save_path} is waiting for you!")
62+
nc.users.notifications.create(f"{input_file.name} finished!", f"{save_path} is waiting for you!")
6563
except Exception as e:
6664
nc.log(LogLvl.ERROR, str(e))
6765
nc.users.notifications.create("Error occurred", "Error information was written to log file")
@@ -73,7 +71,7 @@ async def video_to_gif(
7371
nc: Annotated[NextcloudApp, Depends(nc_app)],
7472
background_tasks: BackgroundTasks,
7573
):
76-
background_tasks.add_task(convert_video_to_gif, file.actionFile, nc)
74+
background_tasks.add_task(convert_video_to_gif, file.actionFile.to_fs_node(), nc)
7775
return Response()
7876

7977

nc_py_api/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
from . import ex_app, options
44
from ._exceptions import NextcloudException, NextcloudExceptionNotFound
55
from ._version import __version__
6-
from .files import FsNode
7-
from .files.sharing import SharePermissions, ShareType
6+
from .files import FilePermissions, FsNode
7+
from .files.sharing import ShareType
88
from .nextcloud import Nextcloud, NextcloudApp

nc_py_api/ex_app/ui/files.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
"""Nextcloud API for working with drop-down file's menu."""
2+
import os
3+
from datetime import datetime, timezone
4+
25
from pydantic import BaseModel
36

47
from ..._exceptions import NextcloudExceptionNotFound
58
from ..._misc import require_capabilities
69
from ..._session import NcSessionApp
10+
from ...files import FilePermissions, FsNode
711

812
ENDPOINT_SUFFIX = "files/actions/menu"
913

@@ -16,8 +20,48 @@ class UiActionFileInfo(BaseModel):
1620
directory: str
1721
etag: str
1822
mime: str
23+
fileType: str
24+
size: int
1925
favorite: str
2026
permissions: int
27+
mtime: int
28+
userId: str
29+
shared: str
30+
31+
def to_fs_node(self) -> FsNode:
32+
"""Returns created ``FsNode`` from the file info given.
33+
34+
.. note:: :py:class:FsNode.file_id in this case is ``without`` **instance_id**
35+
and equal to :py:class:FsNode.info.fileid.
36+
"""
37+
user_path = os.path.join(self.directory, self.name).rstrip("/")
38+
is_dir = bool(self.fileType.lower() == "dir")
39+
if is_dir:
40+
user_path += "/"
41+
full_path = os.path.join(f"files/{self.userId}", user_path.lstrip("/"))
42+
43+
permissions = "S" if self.shared.lower() == "true" else ""
44+
if self.permissions & FilePermissions.PERMISSION_SHARE:
45+
permissions += "R"
46+
if self.permissions & FilePermissions.PERMISSION_READ:
47+
permissions += "G"
48+
if self.permissions & FilePermissions.PERMISSION_DELETE:
49+
permissions += "D"
50+
if self.permissions & FilePermissions.PERMISSION_UPDATE:
51+
permissions += "NV" if is_dir else "NVW"
52+
if is_dir and self.permissions & FilePermissions.PERMISSION_CREATE:
53+
permissions += "CK"
54+
return FsNode(
55+
full_path,
56+
etag=self.etag,
57+
size=self.size,
58+
content_length=0 if is_dir else self.size,
59+
permissions=permissions,
60+
favorite=bool(self.favorite.lower() == "true"),
61+
file_id=self.fileId,
62+
fileid=self.fileId,
63+
last_modified=datetime.utcfromtimestamp(self.mtime).replace(tzinfo=timezone.utc),
64+
)
2165

2266

2367
class UiFileActionHandlerInfo(BaseModel):

nc_py_api/files/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dataclasses
44
import datetime
55
import email.utils
6+
import enum
67
import typing
78

89

@@ -37,7 +38,7 @@ def __init__(self, **kwargs):
3738
def last_modified(self) -> datetime.datetime:
3839
"""Time when the object was last modified.
3940
40-
.. note:: ETag if more preferable way to check if the object was changed.
41+
.. note:: ETag is a more preferable way to check if the object was changed.
4142
"""
4243
return self._last_modified
4344

@@ -148,3 +149,18 @@ def is_creatable(self) -> bool:
148149
if not self.is_dir:
149150
return False
150151
return self.info.permissions.find("CK") != -1
152+
153+
154+
class FilePermissions(enum.IntFlag):
155+
"""List of available permissions for files/directories."""
156+
157+
PERMISSION_READ = 1
158+
"""Access to read"""
159+
PERMISSION_UPDATE = 2
160+
"""Access to write"""
161+
PERMISSION_CREATE = 4
162+
"""Access to create new objects in the directory"""
163+
PERMISSION_DELETE = 8
164+
"""Access to remove object(s)"""
165+
PERMISSION_SHARE = 16
166+
"""Access to re-share object(s)"""

nc_py_api/files/sharing.py

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,7 @@
44
import typing
55

66
from .. import _misc, _session
7-
from . import FsNode
8-
9-
10-
class SharePermissions(enum.IntFlag):
11-
"""The share permissions to be set."""
12-
13-
PERMISSION_READ = 1
14-
"""Access to read"""
15-
PERMISSION_UPDATE = 2
16-
"""Access to write"""
17-
PERMISSION_CREATE = 4
18-
"""Access to create new objects in the share"""
19-
PERMISSION_DELETE = 8
20-
"""Access to remove objects in the share"""
21-
PERMISSION_SHARE = 16
22-
"""Access to re-share objects in the share"""
7+
from . import FilePermissions, FsNode
238

249

2510
class ShareType(enum.IntEnum):
@@ -71,9 +56,9 @@ def share_with(self) -> str:
7156
return self.raw_data["share_with"]
7257

7358
@property
74-
def permissions(self) -> SharePermissions:
59+
def permissions(self) -> FilePermissions:
7560
"""Recipient permissions."""
76-
return SharePermissions(int(self.raw_data["permissions"]))
61+
return FilePermissions(int(self.raw_data["permissions"]))
7762

7863
@property
7964
def url(self) -> str:
@@ -186,15 +171,15 @@ def create(
186171
self,
187172
path: typing.Union[str, FsNode],
188173
share_type: ShareType,
189-
permissions: typing.Optional[SharePermissions] = None,
174+
permissions: typing.Optional[FilePermissions] = None,
190175
share_with: str = "",
191176
**kwargs,
192177
) -> Share:
193178
"""Creates a new share.
194179
195180
:param path: The path of an existing file/directory.
196181
:param share_type: :py:class:`~nc_py_api.files.sharing.ShareType` value.
197-
:param permissions: combination of the :py:class:`~nc_py_api.files.sharing.SharePermissions` object values.
182+
:param permissions: combination of the :py:class:`~nc_py_api.files.FilePermissions` values.
198183
:param share_with: the recipient of the shared object.
199184
:param kwargs: See below.
200185

0 commit comments

Comments
 (0)