|
| 1 | +""" |
| 2 | +Nextcloud API for working with the files shares. |
| 3 | +""" |
| 4 | + |
| 5 | +from typing import Union |
| 6 | + |
| 7 | +from ._session import NcSessionBasic |
| 8 | +from .constants import SharePermissions, ShareType |
| 9 | +from .files import FsNode |
| 10 | +from .misc import check_capabilities, require_capabilities |
| 11 | + |
| 12 | +ENDPOINT_BASE = "/ocs/v1.php/apps/files_sharing/api/v1/" |
| 13 | + |
| 14 | + |
| 15 | +class Share: |
| 16 | + """Class represents one Nextcloud Share.""" |
| 17 | + |
| 18 | + def __init__(self, raw_data: dict): |
| 19 | + self.raw_data = raw_data |
| 20 | + |
| 21 | + @property |
| 22 | + def share_id(self) -> int: |
| 23 | + return int(self.raw_data["id"]) |
| 24 | + |
| 25 | + @property |
| 26 | + def type(self) -> ShareType: |
| 27 | + return ShareType(int(self.raw_data["share_type"])) |
| 28 | + |
| 29 | + @property |
| 30 | + def permissions(self) -> SharePermissions: |
| 31 | + """Recipient permissions""" |
| 32 | + |
| 33 | + return SharePermissions(int(self.raw_data["permissions"])) |
| 34 | + |
| 35 | + @property |
| 36 | + def url(self) -> str: |
| 37 | + return self.raw_data.get("url", "") |
| 38 | + |
| 39 | + @property |
| 40 | + def path(self) -> str: |
| 41 | + return self.raw_data.get("path", "") |
| 42 | + |
| 43 | + @property |
| 44 | + def label(self) -> str: |
| 45 | + return self.raw_data.get("label", "") |
| 46 | + |
| 47 | + @property |
| 48 | + def note(self) -> str: |
| 49 | + return self.raw_data.get("note", "") |
| 50 | + |
| 51 | + @property |
| 52 | + def mimetype(self) -> str: |
| 53 | + return self.raw_data.get("mimetype", "") |
| 54 | + |
| 55 | + |
| 56 | +class FilesSharingAPI: |
| 57 | + """This class provides all File Sharing functionality.""" |
| 58 | + |
| 59 | + def __init__(self, session: NcSessionBasic): |
| 60 | + self._session = session |
| 61 | + |
| 62 | + @property |
| 63 | + def available(self) -> bool: |
| 64 | + """Returns True if the Nextcloud instance supports this feature, False otherwise.""" |
| 65 | + |
| 66 | + return not check_capabilities("files_sharing", self._session.capabilities) |
| 67 | + |
| 68 | + def get_list( |
| 69 | + self, shared_with_me=False, reshares=False, subfiles=False, path: Union[str, FsNode] = "" |
| 70 | + ) -> list[Share]: |
| 71 | + """Returns lists of shares.""" |
| 72 | + |
| 73 | + require_capabilities("files_sharing", self._session.capabilities) |
| 74 | + path = path.path if isinstance(path, FsNode) else path |
| 75 | + params = { |
| 76 | + "shared_with_me": "true" if shared_with_me else "false", |
| 77 | + "reshares": "true" if reshares else "false", |
| 78 | + "subfiles": "true" if subfiles else "false", |
| 79 | + } |
| 80 | + if path: |
| 81 | + params["path"] = path |
| 82 | + result = self._session.ocs(method="GET", path=f"{ENDPOINT_BASE}/shares", params=params) |
| 83 | + return [Share(i) for i in result] |
| 84 | + |
| 85 | + def create( |
| 86 | + self, |
| 87 | + path: Union[str, FsNode], |
| 88 | + permissions: SharePermissions, |
| 89 | + share_type: ShareType, |
| 90 | + share_with: str = "", |
| 91 | + **kwargs, |
| 92 | + ) -> Share: |
| 93 | + """Creates a new share. |
| 94 | +
|
| 95 | + :param path: The path of an existing file/directory. |
| 96 | + :param permissions: combination of the :py:class:`~nc_py_api.SharePermissions` object values. |
| 97 | + :param share_type: :py:class:`~nc_py_api.ShareType` value. |
| 98 | + :param share_with: the recipient of the shared object. |
| 99 | + :param kwargs: *Additionally supported arguments* |
| 100 | +
|
| 101 | + Additionally supported arguments: |
| 102 | + ``public`` - boolean indicating should share be available for non-registered users. |
| 103 | + default = ``False`` |
| 104 | + ``password`` - string with password to protect share. |
| 105 | + default = ``""`` |
| 106 | + ``send_password_by_talk`` - boolean indicating should password be automatically delivered using Talk. |
| 107 | + default = ``False`` |
| 108 | + ``expire_date`` - py:class:`datetime` time when share should expire. `hours, minutes, seconds` are ignored. |
| 109 | + default = None |
| 110 | + ``note`` - string with note, if any. |
| 111 | + default = ``""`` |
| 112 | + ``label`` - string with label, if any. |
| 113 | + default = ``""`` |
| 114 | + """ |
| 115 | + |
| 116 | + require_capabilities("files_sharing", self._session.capabilities) |
| 117 | + path = path.path if isinstance(path, FsNode) else path |
| 118 | + params = { |
| 119 | + "path": path, |
| 120 | + "permissions": int(permissions), |
| 121 | + "shareType": int(share_type), |
| 122 | + } |
| 123 | + if share_with: |
| 124 | + kwargs["shareWith"] = share_with |
| 125 | + if kwargs.get("public", False): |
| 126 | + params["publicUpload"] = "true" |
| 127 | + if "password" in kwargs: |
| 128 | + params["publicUpload"] = kwargs["password"] |
| 129 | + if kwargs.get("send_password_by_talk", False): |
| 130 | + params["sendPasswordByTalk"] = "true" |
| 131 | + if "expire_date" in kwargs: |
| 132 | + params["expireDate"] = kwargs["expire_date"].isoformat() |
| 133 | + if "note" in kwargs: |
| 134 | + params["note"] = kwargs["note"] |
| 135 | + if "label" in kwargs: |
| 136 | + params["label"] = kwargs["label"] |
| 137 | + return Share(self._session.ocs(method="POST", path=f"{ENDPOINT_BASE}/shares", params=params)) |
| 138 | + |
| 139 | + def delete(self, share_id: Union[int, Share]) -> None: |
| 140 | + """Removes the given share. |
| 141 | +
|
| 142 | + :param share_id: The Share object or an ID of the share. |
| 143 | + """ |
| 144 | + |
| 145 | + share_id = share_id.share_id if isinstance(share_id, Share) else share_id |
| 146 | + self._session.ocs(method="DELETE", path=f"{ENDPOINT_BASE}/shares/{share_id}") |
0 commit comments