nc-py-api 0.12.0__py3-none-any.whl → 0.14.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nc_py_api/__init__.py +1 -1
- nc_py_api/_session.py +17 -3
- nc_py_api/_version.py +1 -1
- nc_py_api/ex_app/__init__.py +1 -1
- nc_py_api/ex_app/events_listener.py +137 -0
- nc_py_api/ex_app/occ_commands.py +153 -0
- nc_py_api/ex_app/providers/providers.py +7 -0
- nc_py_api/ex_app/providers/task_processing.py +189 -0
- nc_py_api/ex_app/ui/files_actions.py +45 -1
- nc_py_api/files/__init__.py +9 -1
- nc_py_api/files/_files.py +12 -0
- nc_py_api/files/files.py +14 -482
- nc_py_api/files/files_async.py +523 -0
- nc_py_api/loginflow_v2.py +161 -0
- nc_py_api/nextcloud.py +42 -5
- nc_py_api/users.py +1 -1
- {nc_py_api-0.12.0.dist-info → nc_py_api-0.14.0.dist-info}/METADATA +16 -4
- {nc_py_api-0.12.0.dist-info → nc_py_api-0.14.0.dist-info}/RECORD +21 -16
- {nc_py_api-0.12.0.dist-info → nc_py_api-0.14.0.dist-info}/WHEEL +1 -1
- {nc_py_api-0.12.0.dist-info → nc_py_api-0.14.0.dist-info}/licenses/AUTHORS +0 -0
- {nc_py_api-0.12.0.dist-info → nc_py_api-0.14.0.dist-info}/licenses/LICENSE.txt +0 -0
nc_py_api/__init__.py
CHANGED
|
@@ -7,6 +7,6 @@ from ._exceptions import (
|
|
|
7
7
|
NextcloudMissingCapabilities,
|
|
8
8
|
)
|
|
9
9
|
from ._version import __version__
|
|
10
|
-
from .files import FilePermissions, FsNode, LockType
|
|
10
|
+
from .files import FilePermissions, FsNode, LockType, SystemTag
|
|
11
11
|
from .files.sharing import ShareType
|
|
12
12
|
from .nextcloud import AsyncNextcloud, AsyncNextcloudApp, Nextcloud, NextcloudApp
|
nc_py_api/_session.py
CHANGED
|
@@ -103,7 +103,10 @@ class Config(BasicConfig):
|
|
|
103
103
|
|
|
104
104
|
def __init__(self, **kwargs):
|
|
105
105
|
super().__init__(**kwargs)
|
|
106
|
-
|
|
106
|
+
nc_auth_user = self._get_config_value("nc_auth_user", raise_not_found=False, **kwargs)
|
|
107
|
+
nc_auth_pass = self._get_config_value("nc_auth_pass", raise_not_found=False, **kwargs)
|
|
108
|
+
if nc_auth_user and nc_auth_pass:
|
|
109
|
+
self.auth = (nc_auth_user, nc_auth_pass)
|
|
107
110
|
|
|
108
111
|
|
|
109
112
|
@dataclass
|
|
@@ -176,6 +179,11 @@ class NcSessionBase(ABC):
|
|
|
176
179
|
"""Return base url for the App Ecosystem endpoints."""
|
|
177
180
|
return "/ocs/v1.php/apps/app_api/api/v1"
|
|
178
181
|
|
|
182
|
+
@property
|
|
183
|
+
def ae_url_v2(self) -> str:
|
|
184
|
+
"""Return base url for the App Ecosystem endpoints(version 2)."""
|
|
185
|
+
return "/ocs/v1.php/apps/app_api/api/v2"
|
|
186
|
+
|
|
179
187
|
|
|
180
188
|
class NcSessionBasic(NcSessionBase, ABC):
|
|
181
189
|
adapter: Client
|
|
@@ -189,13 +197,16 @@ class NcSessionBasic(NcSessionBase, ABC):
|
|
|
189
197
|
content: bytes | str | typing.Iterable[bytes] | typing.AsyncIterable[bytes] | None = None,
|
|
190
198
|
json: dict | list | None = None,
|
|
191
199
|
params: dict | None = None,
|
|
200
|
+
files: dict | None = None,
|
|
192
201
|
**kwargs,
|
|
193
202
|
):
|
|
194
203
|
self.init_adapter()
|
|
195
204
|
info = f"request: {method} {path}"
|
|
196
205
|
nested_req = kwargs.pop("nested_req", False)
|
|
197
206
|
try:
|
|
198
|
-
response = self.adapter.request(
|
|
207
|
+
response = self.adapter.request(
|
|
208
|
+
method, path, content=content, json=json, params=params, files=files, **kwargs
|
|
209
|
+
)
|
|
199
210
|
except ReadTimeout:
|
|
200
211
|
raise NextcloudException(408, info=info) from None
|
|
201
212
|
|
|
@@ -307,13 +318,16 @@ class AsyncNcSessionBasic(NcSessionBase, ABC):
|
|
|
307
318
|
content: bytes | str | typing.Iterable[bytes] | typing.AsyncIterable[bytes] | None = None,
|
|
308
319
|
json: dict | list | None = None,
|
|
309
320
|
params: dict | None = None,
|
|
321
|
+
files: dict | None = None,
|
|
310
322
|
**kwargs,
|
|
311
323
|
):
|
|
312
324
|
self.init_adapter()
|
|
313
325
|
info = f"request: {method} {path}"
|
|
314
326
|
nested_req = kwargs.pop("nested_req", False)
|
|
315
327
|
try:
|
|
316
|
-
response = await self.adapter.request(
|
|
328
|
+
response = await self.adapter.request(
|
|
329
|
+
method, path, content=content, json=json, params=params, files=files, **kwargs
|
|
330
|
+
)
|
|
317
331
|
except ReadTimeout:
|
|
318
332
|
raise NextcloudException(408, info=info) from None
|
|
319
333
|
|
nc_py_api/_version.py
CHANGED
nc_py_api/ex_app/__init__.py
CHANGED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Nextcloud API for registering Events listeners for ExApps."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
|
|
5
|
+
from .._exceptions import NextcloudExceptionNotFound
|
|
6
|
+
from .._misc import require_capabilities
|
|
7
|
+
from .._session import AsyncNcSessionApp, NcSessionApp
|
|
8
|
+
|
|
9
|
+
_EP_SUFFIX: str = "events_listener"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclasses.dataclass
|
|
13
|
+
class EventsListener:
|
|
14
|
+
"""EventsListener description."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, raw_data: dict):
|
|
17
|
+
self._raw_data = raw_data
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def event_type(self) -> str:
|
|
21
|
+
"""Main type of event, e.g. ``node_event``."""
|
|
22
|
+
return self._raw_data["event_type"]
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def event_subtypes(self) -> str:
|
|
26
|
+
"""Subtypes for which fire event, e.g. ``NodeCreatedEvent``, ``NodeDeletedEvent``."""
|
|
27
|
+
return self._raw_data["event_subtypes"]
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def action_handler(self) -> str:
|
|
31
|
+
"""Relative ExApp url which will be called by Nextcloud."""
|
|
32
|
+
return self._raw_data["action_handler"]
|
|
33
|
+
|
|
34
|
+
def __repr__(self):
|
|
35
|
+
return f"<{self.__class__.__name__} event_type={self.event_type}, handler={self.action_handler}>"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class EventsListenerAPI:
|
|
39
|
+
"""API for registering Events listeners, avalaible as **nc.events_handler.<method>**."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, session: NcSessionApp):
|
|
42
|
+
self._session = session
|
|
43
|
+
|
|
44
|
+
def register(
|
|
45
|
+
self,
|
|
46
|
+
event_type: str,
|
|
47
|
+
callback_url: str,
|
|
48
|
+
event_subtypes: list[str] | None = None,
|
|
49
|
+
) -> None:
|
|
50
|
+
"""Registers or edits the events listener."""
|
|
51
|
+
if event_subtypes is None:
|
|
52
|
+
event_subtypes = []
|
|
53
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
54
|
+
params = {
|
|
55
|
+
"eventType": event_type,
|
|
56
|
+
"actionHandler": callback_url,
|
|
57
|
+
"eventSubtypes": event_subtypes,
|
|
58
|
+
}
|
|
59
|
+
self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
60
|
+
|
|
61
|
+
def unregister(self, event_type: str, not_fail=True) -> None:
|
|
62
|
+
"""Removes the events listener."""
|
|
63
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
64
|
+
try:
|
|
65
|
+
self._session.ocs(
|
|
66
|
+
"DELETE",
|
|
67
|
+
f"{self._session.ae_url}/{_EP_SUFFIX}",
|
|
68
|
+
params={"eventType": event_type},
|
|
69
|
+
)
|
|
70
|
+
except NextcloudExceptionNotFound as e:
|
|
71
|
+
if not not_fail:
|
|
72
|
+
raise e from None
|
|
73
|
+
|
|
74
|
+
def get_entry(self, event_type: str) -> EventsListener | None:
|
|
75
|
+
"""Get information about the event listener."""
|
|
76
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
77
|
+
try:
|
|
78
|
+
return EventsListener(
|
|
79
|
+
self._session.ocs(
|
|
80
|
+
"GET",
|
|
81
|
+
f"{self._session.ae_url}/{_EP_SUFFIX}",
|
|
82
|
+
params={"eventType": event_type},
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
except NextcloudExceptionNotFound:
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class AsyncEventsListenerAPI:
|
|
90
|
+
"""API for registering Events listeners, avalaible as **nc.events_handler.<method>**."""
|
|
91
|
+
|
|
92
|
+
def __init__(self, session: AsyncNcSessionApp):
|
|
93
|
+
self._session = session
|
|
94
|
+
|
|
95
|
+
async def register(
|
|
96
|
+
self,
|
|
97
|
+
event_type: str,
|
|
98
|
+
callback_url: str,
|
|
99
|
+
event_subtypes: list[str] | None = None,
|
|
100
|
+
) -> None:
|
|
101
|
+
"""Registers or edits the events listener."""
|
|
102
|
+
if event_subtypes is None:
|
|
103
|
+
event_subtypes = []
|
|
104
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
105
|
+
params = {
|
|
106
|
+
"eventType": event_type,
|
|
107
|
+
"actionHandler": callback_url,
|
|
108
|
+
"eventSubtypes": event_subtypes,
|
|
109
|
+
}
|
|
110
|
+
await self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
111
|
+
|
|
112
|
+
async def unregister(self, event_type: str, not_fail=True) -> None:
|
|
113
|
+
"""Removes the events listener."""
|
|
114
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
115
|
+
try:
|
|
116
|
+
await self._session.ocs(
|
|
117
|
+
"DELETE",
|
|
118
|
+
f"{self._session.ae_url}/{_EP_SUFFIX}",
|
|
119
|
+
params={"eventType": event_type},
|
|
120
|
+
)
|
|
121
|
+
except NextcloudExceptionNotFound as e:
|
|
122
|
+
if not not_fail:
|
|
123
|
+
raise e from None
|
|
124
|
+
|
|
125
|
+
async def get_entry(self, event_type: str) -> EventsListener | None:
|
|
126
|
+
"""Get information about the event listener."""
|
|
127
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
128
|
+
try:
|
|
129
|
+
return EventsListener(
|
|
130
|
+
await self._session.ocs(
|
|
131
|
+
"GET",
|
|
132
|
+
f"{self._session.ae_url}/{_EP_SUFFIX}",
|
|
133
|
+
params={"eventType": event_type},
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
except NextcloudExceptionNotFound:
|
|
137
|
+
return None
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Nextcloud API for registering OCC commands for ExApps."""
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
|
|
5
|
+
from .._exceptions import NextcloudExceptionNotFound
|
|
6
|
+
from .._misc import clear_from_params_empty, require_capabilities
|
|
7
|
+
from .._session import AsyncNcSessionApp, NcSessionApp
|
|
8
|
+
|
|
9
|
+
_EP_SUFFIX: str = "occ_command"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclasses.dataclass
|
|
13
|
+
class OccCommand:
|
|
14
|
+
"""OccCommand description."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, raw_data: dict):
|
|
17
|
+
self._raw_data = raw_data
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def name(self) -> str:
|
|
21
|
+
"""Unique ID for the command."""
|
|
22
|
+
return self._raw_data["name"]
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def description(self) -> str:
|
|
26
|
+
"""Command description."""
|
|
27
|
+
return self._raw_data["description"]
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def hidden(self) -> bool:
|
|
31
|
+
"""Flag determining ss command hidden or not."""
|
|
32
|
+
return bool(self._raw_data["hidden"])
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def arguments(self) -> dict:
|
|
36
|
+
"""Look at PHP Symfony framework for details."""
|
|
37
|
+
return self._raw_data["arguments"]
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def options(self) -> str:
|
|
41
|
+
"""Look at PHP Symfony framework for details."""
|
|
42
|
+
return self._raw_data["options"]
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def usages(self) -> str:
|
|
46
|
+
"""Look at PHP Symfony framework for details."""
|
|
47
|
+
return self._raw_data["usages"]
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def action_handler(self) -> str:
|
|
51
|
+
"""Relative ExApp url which will be called by Nextcloud."""
|
|
52
|
+
return self._raw_data["execute_handler"]
|
|
53
|
+
|
|
54
|
+
def __repr__(self):
|
|
55
|
+
return f"<{self.__class__.__name__} name={self.name}, handler={self.action_handler}>"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class OccCommandsAPI:
|
|
59
|
+
"""API for registering OCC commands, avalaible as **nc.occ_command.<method>**."""
|
|
60
|
+
|
|
61
|
+
def __init__(self, session: NcSessionApp):
|
|
62
|
+
self._session = session
|
|
63
|
+
|
|
64
|
+
def register(
|
|
65
|
+
self,
|
|
66
|
+
name: str,
|
|
67
|
+
callback_url: str,
|
|
68
|
+
arguments: list | None = None,
|
|
69
|
+
options: list | None = None,
|
|
70
|
+
usages: list | None = None,
|
|
71
|
+
description: str = "",
|
|
72
|
+
hidden: bool = False,
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Registers or edit the OCC command."""
|
|
75
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
76
|
+
params = {
|
|
77
|
+
"name": name,
|
|
78
|
+
"description": description,
|
|
79
|
+
"arguments": arguments,
|
|
80
|
+
"hidden": int(hidden),
|
|
81
|
+
"options": options,
|
|
82
|
+
"usages": usages,
|
|
83
|
+
"execute_handler": callback_url,
|
|
84
|
+
}
|
|
85
|
+
clear_from_params_empty(["arguments", "options", "usages"], params)
|
|
86
|
+
self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
87
|
+
|
|
88
|
+
def unregister(self, name: str, not_fail=True) -> None:
|
|
89
|
+
"""Removes the OCC command."""
|
|
90
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
91
|
+
try:
|
|
92
|
+
self._session.ocs("DELETE", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name})
|
|
93
|
+
except NextcloudExceptionNotFound as e:
|
|
94
|
+
if not not_fail:
|
|
95
|
+
raise e from None
|
|
96
|
+
|
|
97
|
+
def get_entry(self, name: str) -> OccCommand | None:
|
|
98
|
+
"""Get information of the OCC command."""
|
|
99
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
100
|
+
try:
|
|
101
|
+
return OccCommand(self._session.ocs("GET", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name}))
|
|
102
|
+
except NextcloudExceptionNotFound:
|
|
103
|
+
return None
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class AsyncOccCommandsAPI:
|
|
107
|
+
"""Async API for registering OCC commands, avalaible as **nc.occ_command.<method>**."""
|
|
108
|
+
|
|
109
|
+
def __init__(self, session: AsyncNcSessionApp):
|
|
110
|
+
self._session = session
|
|
111
|
+
|
|
112
|
+
async def register(
|
|
113
|
+
self,
|
|
114
|
+
name: str,
|
|
115
|
+
callback_url: str,
|
|
116
|
+
arguments: list | None = None,
|
|
117
|
+
options: list | None = None,
|
|
118
|
+
usages: list | None = None,
|
|
119
|
+
description: str = "",
|
|
120
|
+
hidden: bool = False,
|
|
121
|
+
) -> None:
|
|
122
|
+
"""Registers or edit the OCC command."""
|
|
123
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
124
|
+
params = {
|
|
125
|
+
"name": name,
|
|
126
|
+
"description": description,
|
|
127
|
+
"arguments": arguments,
|
|
128
|
+
"hidden": int(hidden),
|
|
129
|
+
"options": options,
|
|
130
|
+
"usages": usages,
|
|
131
|
+
"execute_handler": callback_url,
|
|
132
|
+
}
|
|
133
|
+
clear_from_params_empty(["arguments", "options", "usages"], params)
|
|
134
|
+
await self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
135
|
+
|
|
136
|
+
async def unregister(self, name: str, not_fail=True) -> None:
|
|
137
|
+
"""Removes the OCC command."""
|
|
138
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
139
|
+
try:
|
|
140
|
+
await self._session.ocs("DELETE", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name})
|
|
141
|
+
except NextcloudExceptionNotFound as e:
|
|
142
|
+
if not not_fail:
|
|
143
|
+
raise e from None
|
|
144
|
+
|
|
145
|
+
async def get_entry(self, name: str) -> OccCommand | None:
|
|
146
|
+
"""Get information of the OCC command."""
|
|
147
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
148
|
+
try:
|
|
149
|
+
return OccCommand(
|
|
150
|
+
await self._session.ocs("GET", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name})
|
|
151
|
+
)
|
|
152
|
+
except NextcloudExceptionNotFound:
|
|
153
|
+
return None
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from ..._session import AsyncNcSessionApp, NcSessionApp
|
|
4
4
|
from .speech_to_text import _AsyncSpeechToTextProviderAPI, _SpeechToTextProviderAPI
|
|
5
|
+
from .task_processing import _AsyncTaskProcessingProviderAPI, _TaskProcessingProviderAPI
|
|
5
6
|
from .text_processing import _AsyncTextProcessingProviderAPI, _TextProcessingProviderAPI
|
|
6
7
|
from .translations import _AsyncTranslationsProviderAPI, _TranslationsProviderAPI
|
|
7
8
|
|
|
@@ -15,11 +16,14 @@ class ProvidersApi:
|
|
|
15
16
|
"""TextProcessing Provider API."""
|
|
16
17
|
translations: _TranslationsProviderAPI
|
|
17
18
|
"""Translations Provider API."""
|
|
19
|
+
task_processing: _TaskProcessingProviderAPI
|
|
20
|
+
"""TaskProcessing Provider API."""
|
|
18
21
|
|
|
19
22
|
def __init__(self, session: NcSessionApp):
|
|
20
23
|
self.speech_to_text = _SpeechToTextProviderAPI(session)
|
|
21
24
|
self.text_processing = _TextProcessingProviderAPI(session)
|
|
22
25
|
self.translations = _TranslationsProviderAPI(session)
|
|
26
|
+
self.task_processing = _TaskProcessingProviderAPI(session)
|
|
23
27
|
|
|
24
28
|
|
|
25
29
|
class AsyncProvidersApi:
|
|
@@ -31,8 +35,11 @@ class AsyncProvidersApi:
|
|
|
31
35
|
"""TextProcessing Provider API."""
|
|
32
36
|
translations: _AsyncTranslationsProviderAPI
|
|
33
37
|
"""Translations Provider API."""
|
|
38
|
+
task_processing: _AsyncTaskProcessingProviderAPI
|
|
39
|
+
"""TaskProcessing Provider API."""
|
|
34
40
|
|
|
35
41
|
def __init__(self, session: AsyncNcSessionApp):
|
|
36
42
|
self.speech_to_text = _AsyncSpeechToTextProviderAPI(session)
|
|
37
43
|
self.text_processing = _AsyncTextProcessingProviderAPI(session)
|
|
38
44
|
self.translations = _AsyncTranslationsProviderAPI(session)
|
|
45
|
+
self.task_processing = _AsyncTaskProcessingProviderAPI(session)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Nextcloud API for declaring TaskProcessing provider."""
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import dataclasses
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
from ..._exceptions import NextcloudException, NextcloudExceptionNotFound
|
|
8
|
+
from ..._misc import require_capabilities
|
|
9
|
+
from ..._session import AsyncNcSessionApp, NcSessionApp
|
|
10
|
+
|
|
11
|
+
_EP_SUFFIX: str = "ai_provider/task_processing"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclasses.dataclass
|
|
15
|
+
class TaskProcessingProvider:
|
|
16
|
+
"""TaskProcessing provider description."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, raw_data: dict):
|
|
19
|
+
self._raw_data = raw_data
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def name(self) -> str:
|
|
23
|
+
"""Unique ID for the provider."""
|
|
24
|
+
return self._raw_data["name"]
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def display_name(self) -> str:
|
|
28
|
+
"""Providers display name."""
|
|
29
|
+
return self._raw_data["display_name"]
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def task_type(self) -> str:
|
|
33
|
+
"""The TaskType provided by this provider."""
|
|
34
|
+
return self._raw_data["task_type"]
|
|
35
|
+
|
|
36
|
+
def __repr__(self):
|
|
37
|
+
return f"<{self.__class__.__name__} name={self.name}, type={self.task_type}>"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class _TaskProcessingProviderAPI:
|
|
41
|
+
"""API for TaskProcessing providers, available as **nc.providers.task_processing.<method>**."""
|
|
42
|
+
|
|
43
|
+
def __init__(self, session: NcSessionApp):
|
|
44
|
+
self._session = session
|
|
45
|
+
|
|
46
|
+
def register(self, name: str, display_name: str, task_type: str) -> None:
|
|
47
|
+
"""Registers or edit the TaskProcessing provider."""
|
|
48
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
49
|
+
params = {
|
|
50
|
+
"name": name,
|
|
51
|
+
"displayName": display_name,
|
|
52
|
+
"taskType": task_type,
|
|
53
|
+
}
|
|
54
|
+
self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
55
|
+
|
|
56
|
+
def unregister(self, name: str, not_fail=True) -> None:
|
|
57
|
+
"""Removes TaskProcessing provider."""
|
|
58
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
59
|
+
try:
|
|
60
|
+
self._session.ocs("DELETE", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name})
|
|
61
|
+
except NextcloudExceptionNotFound as e:
|
|
62
|
+
if not not_fail:
|
|
63
|
+
raise e from None
|
|
64
|
+
|
|
65
|
+
def next_task(self, provider_ids: list[str], task_types: list[str]) -> dict[str, typing.Any]:
|
|
66
|
+
"""Get the next task processing task from Nextcloud."""
|
|
67
|
+
with contextlib.suppress(NextcloudException):
|
|
68
|
+
if r := self._session.ocs(
|
|
69
|
+
"GET",
|
|
70
|
+
"/ocs/v2.php/taskprocessing/tasks_provider/next",
|
|
71
|
+
json={"providerIds": provider_ids, "taskTypeIds": task_types},
|
|
72
|
+
):
|
|
73
|
+
return r
|
|
74
|
+
return {}
|
|
75
|
+
|
|
76
|
+
def set_progress(self, task_id: int, progress: float) -> dict[str, typing.Any]:
|
|
77
|
+
"""Report new progress value of the task to Nextcloud. Progress should be in range from 0.0 to 100.0."""
|
|
78
|
+
with contextlib.suppress(NextcloudException):
|
|
79
|
+
if r := self._session.ocs(
|
|
80
|
+
"POST",
|
|
81
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/progress",
|
|
82
|
+
json={"taskId": task_id, "progress": progress / 100.0},
|
|
83
|
+
):
|
|
84
|
+
return r
|
|
85
|
+
return {}
|
|
86
|
+
|
|
87
|
+
def upload_result_file(self, task_id: int, file: bytes | str | typing.Any) -> int:
|
|
88
|
+
"""Uploads file and returns fileID that should be used in the ``report_result`` function.
|
|
89
|
+
|
|
90
|
+
.. note:: ``file`` can be any file-like object.
|
|
91
|
+
"""
|
|
92
|
+
return self._session.ocs(
|
|
93
|
+
"POST",
|
|
94
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/file",
|
|
95
|
+
files={"file": file},
|
|
96
|
+
)["fileId"]
|
|
97
|
+
|
|
98
|
+
def report_result(
|
|
99
|
+
self,
|
|
100
|
+
task_id: int,
|
|
101
|
+
output: dict[str, typing.Any] | None = None,
|
|
102
|
+
error_message: str | None = None,
|
|
103
|
+
) -> dict[str, typing.Any]:
|
|
104
|
+
"""Report result of the task processing to Nextcloud."""
|
|
105
|
+
with contextlib.suppress(NextcloudException):
|
|
106
|
+
if r := self._session.ocs(
|
|
107
|
+
"POST",
|
|
108
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/result",
|
|
109
|
+
json={"taskId": task_id, "output": output, "errorMessage": error_message},
|
|
110
|
+
):
|
|
111
|
+
return r
|
|
112
|
+
return {}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class _AsyncTaskProcessingProviderAPI:
|
|
116
|
+
"""Async API for TaskProcessing providers."""
|
|
117
|
+
|
|
118
|
+
def __init__(self, session: AsyncNcSessionApp):
|
|
119
|
+
self._session = session
|
|
120
|
+
|
|
121
|
+
async def register(self, name: str, display_name: str, task_type: str) -> None:
|
|
122
|
+
"""Registers or edit the TaskProcessing provider."""
|
|
123
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
124
|
+
params = {
|
|
125
|
+
"name": name,
|
|
126
|
+
"displayName": display_name,
|
|
127
|
+
"taskType": task_type,
|
|
128
|
+
}
|
|
129
|
+
await self._session.ocs("POST", f"{self._session.ae_url}/{_EP_SUFFIX}", json=params)
|
|
130
|
+
|
|
131
|
+
async def unregister(self, name: str, not_fail=True) -> None:
|
|
132
|
+
"""Removes TaskProcessing provider."""
|
|
133
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
134
|
+
try:
|
|
135
|
+
await self._session.ocs("DELETE", f"{self._session.ae_url}/{_EP_SUFFIX}", params={"name": name})
|
|
136
|
+
except NextcloudExceptionNotFound as e:
|
|
137
|
+
if not not_fail:
|
|
138
|
+
raise e from None
|
|
139
|
+
|
|
140
|
+
async def next_task(self, provider_ids: list[str], task_types: list[str]) -> dict[str, typing.Any]:
|
|
141
|
+
"""Get the next task processing task from Nextcloud."""
|
|
142
|
+
with contextlib.suppress(NextcloudException):
|
|
143
|
+
if r := await self._session.ocs(
|
|
144
|
+
"GET",
|
|
145
|
+
"/ocs/v2.php/taskprocessing/tasks_provider/next",
|
|
146
|
+
json={"providerIds": provider_ids, "taskTypeIds": task_types},
|
|
147
|
+
):
|
|
148
|
+
return r
|
|
149
|
+
return {}
|
|
150
|
+
|
|
151
|
+
async def set_progress(self, task_id: int, progress: float) -> dict[str, typing.Any]:
|
|
152
|
+
"""Report new progress value of the task to Nextcloud. Progress should be in range from 0.0 to 100.0."""
|
|
153
|
+
with contextlib.suppress(NextcloudException):
|
|
154
|
+
if r := await self._session.ocs(
|
|
155
|
+
"POST",
|
|
156
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/progress",
|
|
157
|
+
json={"taskId": task_id, "progress": progress / 100.0},
|
|
158
|
+
):
|
|
159
|
+
return r
|
|
160
|
+
return {}
|
|
161
|
+
|
|
162
|
+
async def upload_result_file(self, task_id: int, file: bytes | str | typing.Any) -> int:
|
|
163
|
+
"""Uploads file and returns fileID that should be used in the ``report_result`` function.
|
|
164
|
+
|
|
165
|
+
.. note:: ``file`` can be any file-like object.
|
|
166
|
+
"""
|
|
167
|
+
return (
|
|
168
|
+
await self._session.ocs(
|
|
169
|
+
"POST",
|
|
170
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/file",
|
|
171
|
+
files={"file": file},
|
|
172
|
+
)
|
|
173
|
+
)["fileId"]
|
|
174
|
+
|
|
175
|
+
async def report_result(
|
|
176
|
+
self,
|
|
177
|
+
task_id: int,
|
|
178
|
+
output: dict[str, typing.Any] | None = None,
|
|
179
|
+
error_message: str | None = None,
|
|
180
|
+
) -> dict[str, typing.Any]:
|
|
181
|
+
"""Report result of the task processing to Nextcloud."""
|
|
182
|
+
with contextlib.suppress(NextcloudException):
|
|
183
|
+
if r := await self._session.ocs(
|
|
184
|
+
"POST",
|
|
185
|
+
f"/ocs/v2.php/taskprocessing/tasks_provider/{task_id}/result",
|
|
186
|
+
json={"taskId": task_id, "output": output, "errorMessage": error_message},
|
|
187
|
+
):
|
|
188
|
+
return r
|
|
189
|
+
return {}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Nextcloud API for working with drop-down file's menu."""
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
+
import warnings
|
|
4
5
|
|
|
5
6
|
from ..._exceptions import NextcloudExceptionNotFound
|
|
6
7
|
from ..._misc import require_capabilities
|
|
@@ -54,6 +55,11 @@ class UiFileActionEntry:
|
|
|
54
55
|
"""Relative ExApp url which will be called if user click on the entry."""
|
|
55
56
|
return self._raw_data["action_handler"]
|
|
56
57
|
|
|
58
|
+
@property
|
|
59
|
+
def version(self) -> str:
|
|
60
|
+
"""AppAPI `2.6.0` supports new version of UiActions(https://github.com/cloud-py-api/app_api/pull/284)."""
|
|
61
|
+
return self._raw_data.get("version", "1.0")
|
|
62
|
+
|
|
57
63
|
def __repr__(self):
|
|
58
64
|
return f"<{self.__class__.__name__} name={self.name}, mime={self.mime}, handler={self.action_handler}>"
|
|
59
65
|
|
|
@@ -67,7 +73,12 @@ class _UiFilesActionsAPI:
|
|
|
67
73
|
self._session = session
|
|
68
74
|
|
|
69
75
|
def register(self, name: str, display_name: str, callback_url: str, **kwargs) -> None:
|
|
70
|
-
"""Registers the files
|
|
76
|
+
"""Registers the files dropdown menu element."""
|
|
77
|
+
warnings.warn(
|
|
78
|
+
"register() is deprecated and will be removed in a future version. Use register_ex() instead.",
|
|
79
|
+
DeprecationWarning,
|
|
80
|
+
stacklevel=2,
|
|
81
|
+
)
|
|
71
82
|
require_capabilities("app_api", self._session.capabilities)
|
|
72
83
|
params = {
|
|
73
84
|
"name": name,
|
|
@@ -80,6 +91,20 @@ class _UiFilesActionsAPI:
|
|
|
80
91
|
}
|
|
81
92
|
self._session.ocs("POST", f"{self._session.ae_url}/{self._ep_suffix}", json=params)
|
|
82
93
|
|
|
94
|
+
def register_ex(self, name: str, display_name: str, callback_url: str, **kwargs) -> None:
|
|
95
|
+
"""Registers the files dropdown menu element(extended version that receives ``ActionFileInfoEx``)."""
|
|
96
|
+
require_capabilities("app_api", self._session.capabilities)
|
|
97
|
+
params = {
|
|
98
|
+
"name": name,
|
|
99
|
+
"displayName": display_name,
|
|
100
|
+
"actionHandler": callback_url,
|
|
101
|
+
"icon": kwargs.get("icon", ""),
|
|
102
|
+
"mime": kwargs.get("mime", "file"),
|
|
103
|
+
"permissions": kwargs.get("permissions", 31),
|
|
104
|
+
"order": kwargs.get("order", 0),
|
|
105
|
+
}
|
|
106
|
+
self._session.ocs("POST", f"{self._session.ae_url_v2}/{self._ep_suffix}", json=params)
|
|
107
|
+
|
|
83
108
|
def unregister(self, name: str, not_fail=True) -> None:
|
|
84
109
|
"""Removes files dropdown menu element."""
|
|
85
110
|
require_capabilities("app_api", self._session.capabilities)
|
|
@@ -110,6 +135,11 @@ class _AsyncUiFilesActionsAPI:
|
|
|
110
135
|
|
|
111
136
|
async def register(self, name: str, display_name: str, callback_url: str, **kwargs) -> None:
|
|
112
137
|
"""Registers the files a dropdown menu element."""
|
|
138
|
+
warnings.warn(
|
|
139
|
+
"register() is deprecated and will be removed in a future version. Use register_ex() instead.",
|
|
140
|
+
DeprecationWarning,
|
|
141
|
+
stacklevel=2,
|
|
142
|
+
)
|
|
113
143
|
require_capabilities("app_api", await self._session.capabilities)
|
|
114
144
|
params = {
|
|
115
145
|
"name": name,
|
|
@@ -122,6 +152,20 @@ class _AsyncUiFilesActionsAPI:
|
|
|
122
152
|
}
|
|
123
153
|
await self._session.ocs("POST", f"{self._session.ae_url}/{self._ep_suffix}", json=params)
|
|
124
154
|
|
|
155
|
+
async def register_ex(self, name: str, display_name: str, callback_url: str, **kwargs) -> None:
|
|
156
|
+
"""Registers the files dropdown menu element(extended version that receives ``ActionFileInfoEx``)."""
|
|
157
|
+
require_capabilities("app_api", await self._session.capabilities)
|
|
158
|
+
params = {
|
|
159
|
+
"name": name,
|
|
160
|
+
"displayName": display_name,
|
|
161
|
+
"actionHandler": callback_url,
|
|
162
|
+
"icon": kwargs.get("icon", ""),
|
|
163
|
+
"mime": kwargs.get("mime", "file"),
|
|
164
|
+
"permissions": kwargs.get("permissions", 31),
|
|
165
|
+
"order": kwargs.get("order", 0),
|
|
166
|
+
}
|
|
167
|
+
await self._session.ocs("POST", f"{self._session.ae_url_v2}/{self._ep_suffix}", json=params)
|
|
168
|
+
|
|
125
169
|
async def unregister(self, name: str, not_fail=True) -> None:
|
|
126
170
|
"""Removes files dropdown menu element."""
|
|
127
171
|
require_capabilities("app_api", await self._session.capabilities)
|