nc-py-api 0.12.1__tar.gz → 0.15.0__tar.gz
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-0.12.1 → nc_py_api-0.15.0}/CHANGELOG.md +27 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/PKG-INFO +21 -9
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/README.md +5 -5
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/__init__.py +1 -1
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_session.py +18 -4
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_version.py +1 -1
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/apps.py +2 -2
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/__init__.py +1 -1
- nc_py_api-0.15.0/nc_py_api/ex_app/events_listener.py +137 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/integration_fastapi.py +17 -7
- nc_py_api-0.15.0/nc_py_api/ex_app/occ_commands.py +153 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/providers/providers.py +7 -0
- nc_py_api-0.15.0/nc_py_api/ex_app/providers/task_processing.py +197 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/files_actions.py +45 -1
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/files/__init__.py +10 -4
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/files/_files.py +12 -0
- nc_py_api-0.15.0/nc_py_api/files/files.py +514 -0
- nc_py_api-0.12.1/nc_py_api/files/files.py → nc_py_api-0.15.0/nc_py_api/files/files_async.py +14 -473
- nc_py_api-0.15.0/nc_py_api/loginflow_v2.py +161 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/nextcloud.py +53 -9
- nc_py_api-0.15.0/nc_py_api/webhooks.py +210 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/pyproject.toml +117 -57
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/.gitignore +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/AUTHORS +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/LICENSE.txt +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_deffered_error.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_exceptions.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_misc.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_preferences.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_preferences_ex.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_talk_api.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/_theming.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/activity.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/calendar.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/defs.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/misc.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/persist_transformers_cache.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/providers/__init__.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/providers/speech_to_text.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/providers/text_processing.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/providers/translations.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/__init__.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/resources.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/settings.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/top_menu.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/ui/ui.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/ex_app/uvicorn_fastapi.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/files/sharing.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/notes.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/notifications.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/options.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/talk.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/talk_bot.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/user_status.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/users.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/users_groups.py +0 -0
- {nc_py_api-0.12.1 → nc_py_api-0.15.0}/nc_py_api/weather_status.py +0 -0
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.15.0 - 2024-07-19]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Initial Webhooks API support for the upcoming Nextcloud 30. #272
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- NextcloudApp: `fetch_models_task` function now saves paths to downloaded models. #274 Thanks to @kyteinsky
|
|
14
|
+
|
|
15
|
+
## [0.14.0 - 2024-07-09]
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `LoginFlowV2` implementation by @blvdek #255
|
|
20
|
+
- `files.get_tags` function to get all tags assigned to the file or directory. #260
|
|
21
|
+
- NextcloudApp: `nc.ui.files_dropdown_menu.register_ex` to register new version of FileActions(AppAPI 2.6.0+) #252
|
|
22
|
+
- NextcloudApp: `enabled_state` property to check if the current ExApp is disabled or enabled. #268
|
|
23
|
+
- NextcloudApp: support for the new AI API for the Nextcloud 30. #254
|
|
24
|
+
|
|
25
|
+
## [0.13.0 - 2024-04-28]
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- NextcloudApp: `occ` commands registration API(AppAPI 2.5.0+). #247
|
|
30
|
+
- NextcloudApp: `Nodes` events listener registration API(AppAPI 2.5.0+). #249
|
|
31
|
+
|
|
5
32
|
## [0.12.1 - 2024-04-05]
|
|
6
33
|
|
|
7
34
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: nc-py-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: Nextcloud Python Framework
|
|
5
5
|
Project-URL: Changelog, https://github.com/cloud-py-api/nc_py_api/blob/main/CHANGELOG.md
|
|
6
6
|
Project-URL: Documentation, https://cloud-py-api.github.io/nc_py_api/
|
|
@@ -38,13 +38,24 @@ Provides-Extra: app
|
|
|
38
38
|
Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'app'
|
|
39
39
|
Provides-Extra: bench
|
|
40
40
|
Requires-Dist: matplotlib; extra == 'bench'
|
|
41
|
-
Requires-Dist: nc-py-api[app]; extra == 'bench'
|
|
42
41
|
Requires-Dist: numpy; extra == 'bench'
|
|
43
42
|
Requires-Dist: py-cpuinfo; extra == 'bench'
|
|
43
|
+
Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'bench'
|
|
44
44
|
Provides-Extra: calendar
|
|
45
45
|
Requires-Dist: caldav==1.3.6; extra == 'calendar'
|
|
46
46
|
Provides-Extra: dev
|
|
47
|
-
Requires-Dist:
|
|
47
|
+
Requires-Dist: caldav==1.3.6; extra == 'dev'
|
|
48
|
+
Requires-Dist: coverage; extra == 'dev'
|
|
49
|
+
Requires-Dist: huggingface-hub; extra == 'dev'
|
|
50
|
+
Requires-Dist: matplotlib; extra == 'dev'
|
|
51
|
+
Requires-Dist: numpy; extra == 'dev'
|
|
52
|
+
Requires-Dist: pillow; extra == 'dev'
|
|
53
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
54
|
+
Requires-Dist: py-cpuinfo; extra == 'dev'
|
|
55
|
+
Requires-Dist: pylint; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
57
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
58
|
+
Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'dev'
|
|
48
59
|
Provides-Extra: dev-min
|
|
49
60
|
Requires-Dist: coverage; extra == 'dev-min'
|
|
50
61
|
Requires-Dist: huggingface-hub; extra == 'dev-min'
|
|
@@ -55,12 +66,13 @@ Requires-Dist: pytest; extra == 'dev-min'
|
|
|
55
66
|
Requires-Dist: pytest-asyncio; extra == 'dev-min'
|
|
56
67
|
Provides-Extra: docs
|
|
57
68
|
Requires-Dist: autodoc-pydantic>=2.0.1; extra == 'docs'
|
|
58
|
-
Requires-Dist:
|
|
69
|
+
Requires-Dist: caldav==1.3.6; extra == 'docs'
|
|
59
70
|
Requires-Dist: sphinx-copybutton; extra == 'docs'
|
|
60
71
|
Requires-Dist: sphinx-inline-tabs; extra == 'docs'
|
|
61
72
|
Requires-Dist: sphinx-issues>=3.0.1; extra == 'docs'
|
|
62
73
|
Requires-Dist: sphinx-rtd-theme>=1; extra == 'docs'
|
|
63
74
|
Requires-Dist: sphinx>=6.2; extra == 'docs'
|
|
75
|
+
Requires-Dist: uvicorn[standard]>=0.23.2; extra == 'docs'
|
|
64
76
|
Description-Content-Type: text/markdown
|
|
65
77
|
|
|
66
78
|
<p align="center">
|
|
@@ -73,7 +85,7 @@ Description-Content-Type: text/markdown
|
|
|
73
85
|
[](https://cloud-py-api.github.io/nc_py_api/)
|
|
74
86
|
[](https://codecov.io/github/cloud-py-api/nc_py_api)
|
|
75
87
|
|
|
76
|
-

|
|
77
89
|

|
|
78
90
|

|
|
79
91
|

|
|
@@ -89,7 +101,7 @@ Python library that provides a robust and well-documented API that allows develo
|
|
|
89
101
|
* **Sync + Async**: Provides both sync and async APIs.
|
|
90
102
|
|
|
91
103
|
### Capabilities
|
|
92
|
-
| **_Capability_** | Nextcloud
|
|
104
|
+
| **_Capability_** | Nextcloud 27 | Nextcloud 28 | Nextcloud 29 | Nextcloud 30 |
|
|
93
105
|
|-----------------------|:------------:|:------------:|:------------:|:------------:|
|
|
94
106
|
| Calendar | ✅ | ✅ | ✅ | ✅ |
|
|
95
107
|
| File System & Tags | ✅ | ✅ | ✅ | ✅ |
|
|
@@ -99,9 +111,9 @@ Python library that provides a robust and well-documented API that allows develo
|
|
|
99
111
|
| Users & Groups | ✅ | ✅ | ✅ | ✅ |
|
|
100
112
|
| User & Weather status | ✅ | ✅ | ✅ | ✅ |
|
|
101
113
|
| Other APIs*** | ✅ | ✅ | ✅ | ✅ |
|
|
102
|
-
| Talk Bot API* |
|
|
103
|
-
| Settings UI API* | N/A | N/A |
|
|
104
|
-
| AI Providers API** | N/A | N/A |
|
|
114
|
+
| Talk Bot API* | ✅ | ✅ | ✅ | ✅ |
|
|
115
|
+
| Settings UI API* | N/A | N/A | ✅ | ✅ |
|
|
116
|
+
| AI Providers API** | N/A | N/A | ✅ | ✅ |
|
|
105
117
|
|
|
106
118
|
*_available only for **NextcloudApp**_<br>
|
|
107
119
|
**_available only for **NextcloudApp**: SpeechToText, TextProcessing, Translation_<br>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
[](https://cloud-py-api.github.io/nc_py_api/)
|
|
9
9
|
[](https://codecov.io/github/cloud-py-api/nc_py_api)
|
|
10
10
|
|
|
11
|
-

|
|
12
12
|

|
|
13
13
|

|
|
14
14
|

|
|
@@ -24,7 +24,7 @@ Python library that provides a robust and well-documented API that allows develo
|
|
|
24
24
|
* **Sync + Async**: Provides both sync and async APIs.
|
|
25
25
|
|
|
26
26
|
### Capabilities
|
|
27
|
-
| **_Capability_** | Nextcloud
|
|
27
|
+
| **_Capability_** | Nextcloud 27 | Nextcloud 28 | Nextcloud 29 | Nextcloud 30 |
|
|
28
28
|
|-----------------------|:------------:|:------------:|:------------:|:------------:|
|
|
29
29
|
| Calendar | ✅ | ✅ | ✅ | ✅ |
|
|
30
30
|
| File System & Tags | ✅ | ✅ | ✅ | ✅ |
|
|
@@ -34,9 +34,9 @@ Python library that provides a robust and well-documented API that allows develo
|
|
|
34
34
|
| Users & Groups | ✅ | ✅ | ✅ | ✅ |
|
|
35
35
|
| User & Weather status | ✅ | ✅ | ✅ | ✅ |
|
|
36
36
|
| Other APIs*** | ✅ | ✅ | ✅ | ✅ |
|
|
37
|
-
| Talk Bot API* |
|
|
38
|
-
| Settings UI API* | N/A | N/A |
|
|
39
|
-
| AI Providers API** | N/A | N/A |
|
|
37
|
+
| Talk Bot API* | ✅ | ✅ | ✅ | ✅ |
|
|
38
|
+
| Settings UI API* | N/A | N/A | ✅ | ✅ |
|
|
39
|
+
| AI Providers API** | N/A | N/A | ✅ | ✅ |
|
|
40
40
|
|
|
41
41
|
*_available only for **NextcloudApp**_<br>
|
|
42
42
|
**_available only for **NextcloudApp**: SpeechToText, TextProcessing, Translation_<br>
|
|
@@ -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
|
|
@@ -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
|
|
@@ -173,9 +176,14 @@ class NcSessionBase(ABC):
|
|
|
173
176
|
|
|
174
177
|
@property
|
|
175
178
|
def ae_url(self) -> str:
|
|
176
|
-
"""Return base url for the
|
|
179
|
+
"""Return base url for the AppAPI 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 AppAPI 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
|
|
|
@@ -43,8 +43,8 @@ class ExAppInfo:
|
|
|
43
43
|
|
|
44
44
|
@property
|
|
45
45
|
def system(self) -> bool:
|
|
46
|
-
"""Flag indicating if the application is a system application."""
|
|
47
|
-
return
|
|
46
|
+
"""**DEPRECATED** Flag indicating if the application is a system application."""
|
|
47
|
+
return True
|
|
48
48
|
|
|
49
49
|
def __repr__(self):
|
|
50
50
|
return f"<{self.__class__.__name__} id={self.app_id}, ver={self.version}>"
|
|
@@ -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
|
|
@@ -127,22 +127,26 @@ def fetch_models_task(nc: NextcloudApp, models: dict[str, dict], progress_init_s
|
|
|
127
127
|
percent_for_each = min(int((100 - progress_init_start_value) / len(models)), 99)
|
|
128
128
|
for model in models:
|
|
129
129
|
if model.startswith(("http://", "https://")):
|
|
130
|
-
|
|
130
|
+
models[model]["path"] = __fetch_model_as_file(
|
|
131
|
+
current_progress, percent_for_each, nc, model, models[model]
|
|
132
|
+
)
|
|
131
133
|
else:
|
|
132
|
-
|
|
134
|
+
models[model]["path"] = __fetch_model_as_snapshot(
|
|
135
|
+
current_progress, percent_for_each, nc, model, models[model]
|
|
136
|
+
)
|
|
133
137
|
current_progress += percent_for_each
|
|
134
138
|
nc.set_init_status(100)
|
|
135
139
|
|
|
136
140
|
|
|
137
141
|
def __fetch_model_as_file(
|
|
138
142
|
current_progress: int, progress_for_task: int, nc: NextcloudApp, model_path: str, download_options: dict
|
|
139
|
-
) -> None:
|
|
143
|
+
) -> str | None:
|
|
140
144
|
result_path = download_options.pop("save_path", urlparse(model_path).path.split("/")[-1])
|
|
141
145
|
try:
|
|
142
146
|
with httpx.stream("GET", model_path, follow_redirects=True) as response:
|
|
143
147
|
if not response.is_success:
|
|
144
148
|
nc.log(LogLvl.ERROR, f"Downloading of '{model_path}' returned {response.status_code} status.")
|
|
145
|
-
return
|
|
149
|
+
return None
|
|
146
150
|
downloaded_size = 0
|
|
147
151
|
linked_etag = ""
|
|
148
152
|
for each_history in response.history:
|
|
@@ -163,7 +167,7 @@ def __fetch_model_as_file(
|
|
|
163
167
|
sha256_hash.update(byte_block)
|
|
164
168
|
if f'"{sha256_hash.hexdigest()}"' == linked_etag:
|
|
165
169
|
nc.set_init_status(min(current_progress + progress_for_task, 99))
|
|
166
|
-
return
|
|
170
|
+
return None
|
|
167
171
|
|
|
168
172
|
with builtins.open(result_path, "wb") as file:
|
|
169
173
|
last_progress = current_progress
|
|
@@ -174,13 +178,17 @@ def __fetch_model_as_file(
|
|
|
174
178
|
if new_progress != last_progress:
|
|
175
179
|
nc.set_init_status(new_progress)
|
|
176
180
|
last_progress = new_progress
|
|
181
|
+
|
|
182
|
+
return result_path
|
|
177
183
|
except Exception as e: # noqa pylint: disable=broad-exception-caught
|
|
178
184
|
nc.log(LogLvl.ERROR, f"Downloading of '{model_path}' raised an exception: {e}")
|
|
179
185
|
|
|
186
|
+
return None
|
|
187
|
+
|
|
180
188
|
|
|
181
189
|
def __fetch_model_as_snapshot(
|
|
182
190
|
current_progress: int, progress_for_task, nc: NextcloudApp, mode_name: str, download_options: dict
|
|
183
|
-
) ->
|
|
191
|
+
) -> str:
|
|
184
192
|
from huggingface_hub import snapshot_download # noqa isort:skip pylint: disable=C0415 disable=E0401
|
|
185
193
|
from tqdm import tqdm # noqa isort:skip pylint: disable=C0415 disable=E0401
|
|
186
194
|
|
|
@@ -191,7 +199,9 @@ def __fetch_model_as_snapshot(
|
|
|
191
199
|
|
|
192
200
|
workers = download_options.pop("max_workers", 2)
|
|
193
201
|
cache = download_options.pop("cache_dir", persistent_storage())
|
|
194
|
-
snapshot_download(
|
|
202
|
+
return snapshot_download(
|
|
203
|
+
mode_name, tqdm_class=TqdmProgress, **download_options, max_workers=workers, cache_dir=cache
|
|
204
|
+
)
|
|
195
205
|
|
|
196
206
|
|
|
197
207
|
def __nc_app(request: HTTPConnection) -> dict:
|
|
@@ -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)
|