omniplayr-plugins 2026.7.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.
- omniplayr_plugins-2026.7.0/.gitignore +30 -0
- omniplayr_plugins-2026.7.0/PKG-INFO +145 -0
- omniplayr_plugins-2026.7.0/README.md +122 -0
- omniplayr_plugins-2026.7.0/pyproject.toml +43 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/__init__.py +1 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/__init__.py +35 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/_runtime.py +17 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/account.py +86 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/admin.py +18 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/api.py +54 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/backend_config.py +26 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/config.py +22 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/db.py +58 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/diagnostics.py +34 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/functions.py +83 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/health.py +31 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/installer.py +22 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/logging.py +44 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/notifications.py +63 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/passwords.py +18 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/py.typed +0 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/runtime.py +54 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/server.py +34 -0
- omniplayr_plugins-2026.7.0/src/omniplayr/plugins/updater.py +24 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
coverage/
|
|
8
|
+
|
|
9
|
+
# Cache
|
|
10
|
+
__pycache__
|
|
11
|
+
|
|
12
|
+
# TypeScript
|
|
13
|
+
*.tsbuildinfo
|
|
14
|
+
|
|
15
|
+
# Logs
|
|
16
|
+
*.log
|
|
17
|
+
npm-debug.log*
|
|
18
|
+
yarn-debug.log*
|
|
19
|
+
yarn-error.log*
|
|
20
|
+
pnpm-debug.log*
|
|
21
|
+
|
|
22
|
+
# Environment files
|
|
23
|
+
.env
|
|
24
|
+
.env.*
|
|
25
|
+
|
|
26
|
+
# Editor / OS
|
|
27
|
+
.vscode/
|
|
28
|
+
.idea/
|
|
29
|
+
.DS_Store
|
|
30
|
+
Thumbs.db
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: omniplayr-plugins
|
|
3
|
+
Version: 2026.7.0
|
|
4
|
+
Summary: Backend development SDK for OmniPlayr plugins.
|
|
5
|
+
Project-URL: Homepage, https://omniplayr.wokki20.nl/
|
|
6
|
+
Project-URL: Documentation, https://omniplayr.wokki20.nl/docs/plugins/building/backend/
|
|
7
|
+
Project-URL: Repository, https://github.com/OmniPlayr/OmniPlayr-plugin-SDK
|
|
8
|
+
Project-URL: Issues, https://github.com/OmniPlayr/OmniPlayr-plugin-SDK/issues
|
|
9
|
+
Author: OmniPlayr
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: omniplayr,plugins,sdk,typing
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# omniplayr-plugins
|
|
25
|
+
|
|
26
|
+
Backend development SDK for OmniPlayr plugins.
|
|
27
|
+
|
|
28
|
+
Install it in a plugin development environment:
|
|
29
|
+
|
|
30
|
+
```powershell
|
|
31
|
+
pip install omniplayr-plugins
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Plugin authors can import the public backend SDK from one namespace:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from omniplayr.plugins import BackendPlugin, api, register
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This package is intentionally lightweight. It provides type hints, typed
|
|
41
|
+
placeholders, protocols, docstrings, and IDE autocomplete support for backend
|
|
42
|
+
plugin development. The actual runtime implementation is provided by the
|
|
43
|
+
OmniPlayr server and Docker runtime when a plugin is loaded.
|
|
44
|
+
|
|
45
|
+
## Documentation
|
|
46
|
+
|
|
47
|
+
Read the full backend plugin documentation:
|
|
48
|
+
|
|
49
|
+
https://omniplayr.wokki20.nl/docs/plugins/building/backend/#backend-plugin-overview
|
|
50
|
+
|
|
51
|
+
## API Map
|
|
52
|
+
|
|
53
|
+
- `BackendPlugin`, `PluginBase`, `register`, `get_plugin`, `get_backend_plugin_dir`,
|
|
54
|
+
`get_plugin_router`, `load_plugins`
|
|
55
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/#the-setup-function)
|
|
56
|
+
|
|
57
|
+
- `api`, `PluginApi`, `RouteHandler`, `RouteDecorator`
|
|
58
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/routes.html#registering-routes)
|
|
59
|
+
|
|
60
|
+
- `PluginFunctions`, `expose`, `expose_function`, `call`, `call_plugin_function`,
|
|
61
|
+
`is_installed`, `is_plugin_available`, `has_function`,
|
|
62
|
+
`is_plugin_function_available`, `mark_plugin_loaded`, `remove_plugin`,
|
|
63
|
+
`PluginNotAvailableError`,
|
|
64
|
+
`PluginFunctionNotFoundError`
|
|
65
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#available-helpers)
|
|
66
|
+
|
|
67
|
+
- `get_plugin_config`, `reload_plugin_config`, `flatten_plugin_configs`,
|
|
68
|
+
`get_config`, `load_configs`, `flatten_configs`, `flatten_frontend_configs`,
|
|
69
|
+
`TomlValue`, `FlatConfigItem`, `deep_merge`, `sync_config`,
|
|
70
|
+
`start_config_watcher`, `ConfigChangeHandler`
|
|
71
|
+
|
|
72
|
+
- `request_db_access`, `PluginDB`, `ProtectionLevel`, `get_conn`,
|
|
73
|
+
`is_safe_sql_identifier`, `parse_column_type`, `can_convert_column`,
|
|
74
|
+
`init_db`, `init_db_when_ready`
|
|
75
|
+
|
|
76
|
+
- `verify_auth`, `verify_admin`, `verify_token`, `get_admin_status`,
|
|
77
|
+
`match_account`, `get_token_user`, `create_access_token`, `parse_interval`
|
|
78
|
+
|
|
79
|
+
- `list_accounts`, `get_account`, `create_account`, `update_account`,
|
|
80
|
+
`delete_account`, account tokens, password verification, and two-factor
|
|
81
|
+
helpers
|
|
82
|
+
|
|
83
|
+
- `notify`, `notify_once`, `notify_sync`, `notify_once_sync`,
|
|
84
|
+
`get_notifications`, `get_unread_count`, `mark_read`,
|
|
85
|
+
`delete_notification`, `NotificationManager`
|
|
86
|
+
|
|
87
|
+
- `log`, `log_exception`, `get_logs`, exception hook setup helpers,
|
|
88
|
+
diagnostics helpers, `health`, `ServiceStatus`, `HealthResponse`
|
|
89
|
+
|
|
90
|
+
- `fetch_plugin_info`, `install_plugin`, `install_local_plugin`,
|
|
91
|
+
`check_for_updates`, `apply_update`, `start_https_proxy`, `user_warn`
|
|
92
|
+
|
|
93
|
+
## Local Testing
|
|
94
|
+
|
|
95
|
+
From this package:
|
|
96
|
+
|
|
97
|
+
```powershell
|
|
98
|
+
python -m pip install -e .
|
|
99
|
+
python - <<'PY'
|
|
100
|
+
from omniplayr.plugins import BackendPlugin, api, register
|
|
101
|
+
|
|
102
|
+
class MyPlugin(BackendPlugin):
|
|
103
|
+
source_type = "example"
|
|
104
|
+
|
|
105
|
+
register(MyPlugin())
|
|
106
|
+
|
|
107
|
+
@api.get("/health")
|
|
108
|
+
def health() -> dict[str, str]:
|
|
109
|
+
return {"ok": "true"}
|
|
110
|
+
|
|
111
|
+
print("omniplayr.plugins import OK")
|
|
112
|
+
PY
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The SDK exports a PEP 561 `py.typed` marker so type checkers such as Pylance,
|
|
116
|
+
Pyright, and mypy can understand the package.
|
|
117
|
+
|
|
118
|
+
## Deprecation Policy
|
|
119
|
+
|
|
120
|
+
Backend SDK APIs should be deprecated before they are removed. When an API is
|
|
121
|
+
being replaced, the OmniPlayr server should keep a compatibility wrapper with
|
|
122
|
+
metadata at the top of the docstring:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
def old_helper() -> None:
|
|
126
|
+
"""@deprecated=true
|
|
127
|
+
Use `new_helper` instead.
|
|
128
|
+
"""
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The SDK generator records the first backend version where the marker appears in
|
|
132
|
+
`backend/deprecations.json`, then renders the SDK docstring as a normal
|
|
133
|
+
deprecation notice. You can also pin the version manually:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
def old_helper() -> None:
|
|
137
|
+
"""@deprecated=true
|
|
138
|
+
@deprecated_since=2026.7.2
|
|
139
|
+
Use `new_helper` instead.
|
|
140
|
+
"""
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Deprecated APIs remain exported by this SDK for at least one year. They are only
|
|
144
|
+
removed during an annual major compatibility cleanup, so plugin authors have a
|
|
145
|
+
full yearly release window to migrate.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# omniplayr-plugins
|
|
2
|
+
|
|
3
|
+
Backend development SDK for OmniPlayr plugins.
|
|
4
|
+
|
|
5
|
+
Install it in a plugin development environment:
|
|
6
|
+
|
|
7
|
+
```powershell
|
|
8
|
+
pip install omniplayr-plugins
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Plugin authors can import the public backend SDK from one namespace:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from omniplayr.plugins import BackendPlugin, api, register
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This package is intentionally lightweight. It provides type hints, typed
|
|
18
|
+
placeholders, protocols, docstrings, and IDE autocomplete support for backend
|
|
19
|
+
plugin development. The actual runtime implementation is provided by the
|
|
20
|
+
OmniPlayr server and Docker runtime when a plugin is loaded.
|
|
21
|
+
|
|
22
|
+
## Documentation
|
|
23
|
+
|
|
24
|
+
Read the full backend plugin documentation:
|
|
25
|
+
|
|
26
|
+
https://omniplayr.wokki20.nl/docs/plugins/building/backend/#backend-plugin-overview
|
|
27
|
+
|
|
28
|
+
## API Map
|
|
29
|
+
|
|
30
|
+
- `BackendPlugin`, `PluginBase`, `register`, `get_plugin`, `get_backend_plugin_dir`,
|
|
31
|
+
`get_plugin_router`, `load_plugins`
|
|
32
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/#the-setup-function)
|
|
33
|
+
|
|
34
|
+
- `api`, `PluginApi`, `RouteHandler`, `RouteDecorator`
|
|
35
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/routes.html#registering-routes)
|
|
36
|
+
|
|
37
|
+
- `PluginFunctions`, `expose`, `expose_function`, `call`, `call_plugin_function`,
|
|
38
|
+
`is_installed`, `is_plugin_available`, `has_function`,
|
|
39
|
+
`is_plugin_function_available`, `mark_plugin_loaded`, `remove_plugin`,
|
|
40
|
+
`PluginNotAvailableError`,
|
|
41
|
+
`PluginFunctionNotFoundError`
|
|
42
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#available-helpers)
|
|
43
|
+
|
|
44
|
+
- `get_plugin_config`, `reload_plugin_config`, `flatten_plugin_configs`,
|
|
45
|
+
`get_config`, `load_configs`, `flatten_configs`, `flatten_frontend_configs`,
|
|
46
|
+
`TomlValue`, `FlatConfigItem`, `deep_merge`, `sync_config`,
|
|
47
|
+
`start_config_watcher`, `ConfigChangeHandler`
|
|
48
|
+
|
|
49
|
+
- `request_db_access`, `PluginDB`, `ProtectionLevel`, `get_conn`,
|
|
50
|
+
`is_safe_sql_identifier`, `parse_column_type`, `can_convert_column`,
|
|
51
|
+
`init_db`, `init_db_when_ready`
|
|
52
|
+
|
|
53
|
+
- `verify_auth`, `verify_admin`, `verify_token`, `get_admin_status`,
|
|
54
|
+
`match_account`, `get_token_user`, `create_access_token`, `parse_interval`
|
|
55
|
+
|
|
56
|
+
- `list_accounts`, `get_account`, `create_account`, `update_account`,
|
|
57
|
+
`delete_account`, account tokens, password verification, and two-factor
|
|
58
|
+
helpers
|
|
59
|
+
|
|
60
|
+
- `notify`, `notify_once`, `notify_sync`, `notify_once_sync`,
|
|
61
|
+
`get_notifications`, `get_unread_count`, `mark_read`,
|
|
62
|
+
`delete_notification`, `NotificationManager`
|
|
63
|
+
|
|
64
|
+
- `log`, `log_exception`, `get_logs`, exception hook setup helpers,
|
|
65
|
+
diagnostics helpers, `health`, `ServiceStatus`, `HealthResponse`
|
|
66
|
+
|
|
67
|
+
- `fetch_plugin_info`, `install_plugin`, `install_local_plugin`,
|
|
68
|
+
`check_for_updates`, `apply_update`, `start_https_proxy`, `user_warn`
|
|
69
|
+
|
|
70
|
+
## Local Testing
|
|
71
|
+
|
|
72
|
+
From this package:
|
|
73
|
+
|
|
74
|
+
```powershell
|
|
75
|
+
python -m pip install -e .
|
|
76
|
+
python - <<'PY'
|
|
77
|
+
from omniplayr.plugins import BackendPlugin, api, register
|
|
78
|
+
|
|
79
|
+
class MyPlugin(BackendPlugin):
|
|
80
|
+
source_type = "example"
|
|
81
|
+
|
|
82
|
+
register(MyPlugin())
|
|
83
|
+
|
|
84
|
+
@api.get("/health")
|
|
85
|
+
def health() -> dict[str, str]:
|
|
86
|
+
return {"ok": "true"}
|
|
87
|
+
|
|
88
|
+
print("omniplayr.plugins import OK")
|
|
89
|
+
PY
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The SDK exports a PEP 561 `py.typed` marker so type checkers such as Pylance,
|
|
93
|
+
Pyright, and mypy can understand the package.
|
|
94
|
+
|
|
95
|
+
## Deprecation Policy
|
|
96
|
+
|
|
97
|
+
Backend SDK APIs should be deprecated before they are removed. When an API is
|
|
98
|
+
being replaced, the OmniPlayr server should keep a compatibility wrapper with
|
|
99
|
+
metadata at the top of the docstring:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
def old_helper() -> None:
|
|
103
|
+
"""@deprecated=true
|
|
104
|
+
Use `new_helper` instead.
|
|
105
|
+
"""
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The SDK generator records the first backend version where the marker appears in
|
|
109
|
+
`backend/deprecations.json`, then renders the SDK docstring as a normal
|
|
110
|
+
deprecation notice. You can also pin the version manually:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
def old_helper() -> None:
|
|
114
|
+
"""@deprecated=true
|
|
115
|
+
@deprecated_since=2026.7.2
|
|
116
|
+
Use `new_helper` instead.
|
|
117
|
+
"""
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Deprecated APIs remain exported by this SDK for at least one year. They are only
|
|
121
|
+
removed during an annual major compatibility cleanup, so plugin authors have a
|
|
122
|
+
full yearly release window to migrate.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.26"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "omniplayr-plugins"
|
|
7
|
+
version = "2026.7.0"
|
|
8
|
+
description = "Backend development SDK for OmniPlayr plugins."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "OmniPlayr" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["omniplayr", "plugins", "sdk", "typing"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Typing :: Typed",
|
|
26
|
+
]
|
|
27
|
+
dependencies = []
|
|
28
|
+
|
|
29
|
+
[project.urls]
|
|
30
|
+
Homepage = "https://omniplayr.wokki20.nl/"
|
|
31
|
+
Documentation = "https://omniplayr.wokki20.nl/docs/plugins/building/backend/"
|
|
32
|
+
Repository = "https://github.com/OmniPlayr/OmniPlayr-plugin-SDK"
|
|
33
|
+
Issues = "https://github.com/OmniPlayr/OmniPlayr-plugin-SDK/issues"
|
|
34
|
+
|
|
35
|
+
[tool.hatch.build.targets.wheel]
|
|
36
|
+
packages = ["src/omniplayr"]
|
|
37
|
+
|
|
38
|
+
[tool.hatch.build.targets.sdist]
|
|
39
|
+
include = [
|
|
40
|
+
"README.md",
|
|
41
|
+
"pyproject.toml",
|
|
42
|
+
"src/omniplayr",
|
|
43
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Namespace package for OmniPlayr development SDKs."""
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Public backend development SDK for OmniPlayr plugins."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Callable
|
|
6
|
+
|
|
7
|
+
from ._runtime import OmniPlayrRuntimeUnavailableError
|
|
8
|
+
from ._runtime import runtime_unavailable
|
|
9
|
+
from .account import *
|
|
10
|
+
from .admin import *
|
|
11
|
+
from .api import *
|
|
12
|
+
from .backend_config import *
|
|
13
|
+
from .config import *
|
|
14
|
+
from .db import *
|
|
15
|
+
from .diagnostics import *
|
|
16
|
+
from .functions import *
|
|
17
|
+
from .health import *
|
|
18
|
+
from .installer import *
|
|
19
|
+
from .logging import *
|
|
20
|
+
from .notifications import *
|
|
21
|
+
from .passwords import *
|
|
22
|
+
from .runtime import *
|
|
23
|
+
from .server import *
|
|
24
|
+
from .updater import *
|
|
25
|
+
|
|
26
|
+
BackendPlugin = PluginBase
|
|
27
|
+
call_plugin_function = call
|
|
28
|
+
is_plugin_available = is_installed
|
|
29
|
+
is_plugin_function_available = has_function
|
|
30
|
+
|
|
31
|
+
def expose_function(function_name: str, function: Callable[..., Any] | None = None) -> Any:
|
|
32
|
+
"""Expose a callable for the current backend plugin."""
|
|
33
|
+
raise runtime_unavailable("expose_function")
|
|
34
|
+
|
|
35
|
+
__all__ = ['BACKEND_PRESERVED', 'BOLD', 'BackendPlugin', 'DIM', 'FRONTEND_PRESERVED', 'HealthResponse', 'INITIAL_NOTIFICATIONS', 'LEVEL_COLORS', 'LEVEL_LABELS', 'NotificationManager', 'OmniPlayrRuntimeUnavailableError', 'PROTECTED_TABLES', 'PluginApi', 'PluginBase', 'PluginDB', 'PluginFunctionNotFoundError', 'PluginFunctions', 'PluginNotAvailableError', 'ProtectionLevel', 'RESET', 'ROOT_PRESERVED', 'RouteDecorator', 'RouteHandler', 'ServiceStatus', 'api', 'apply_update', 'call', 'call_plugin_function', 'check_for_updates', 'create_2fa_setup', 'create_access_token', 'create_account', 'create_account_token', 'create_backup_codes', 'delete_2fa', 'delete_account', 'delete_account_token', 'delete_backup_codes', 'delete_notification', 'delete_profile_picture', 'expose', 'expose_function', 'fetch_plugin_info', 'flatten_configs', 'flatten_frontend_configs', 'flatten_plugin_configs', 'get_account', 'get_account_summary', 'get_admin_status', 'get_backend_plugin_dir', 'get_config', 'get_error_counts', 'get_logs', 'get_notifications', 'get_plugin', 'get_plugin_config', 'get_plugin_router', 'get_token_user', 'get_unread_count', 'get_uptime_seconds', 'has_backup_codes', 'has_function', 'health', 'install_local_plugin', 'install_plugin', 'is_installed', 'is_plugin_available', 'is_plugin_function_available', 'list_account_summaries', 'list_accounts', 'load_configs', 'load_plugins', 'log', 'log_exception', 'mark_plugin_loaded', 'mark_read', 'match_account', 'notify', 'notify_once', 'notify_once_sync', 'notify_sync', 'parse_interval', 'password_check', 'password_hash', 'record_error', 'register', 'reload_plugin_config', 'remove_plugin', 'remove_table_protection', 'request_db_access', 'reset_error_counts', 'revoke_token', 'run_diagnostics', 'set_main_loop', 'set_table_protection', 'setup_asyncio_exception_handler', 'setup_exception_hook', 'setup_thread_exception_hook', 'start_diagnostics', 'update_account', 'verify_2fa_code', 'verify_account_password', 'verify_admin', 'verify_auth', 'verify_backup_code', 'verify_token']
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Runtime placeholders for the generated OmniPlayr backend SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OmniPlayrRuntimeUnavailableError(RuntimeError):
|
|
7
|
+
"""Raised when an OmniPlayr server-only API is used outside the runtime."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def runtime_unavailable(name: str) -> OmniPlayrRuntimeUnavailableError:
|
|
11
|
+
"""Return an error for APIs that are only implemented by the server."""
|
|
12
|
+
|
|
13
|
+
return OmniPlayrRuntimeUnavailableError(
|
|
14
|
+
f"{name} is provided by the OmniPlayr backend runtime. "
|
|
15
|
+
"The omniplayr-plugins package only supplies development-time typing, "
|
|
16
|
+
"imports, docstrings, and autocomplete support."
|
|
17
|
+
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `account` helpers."""
|
|
9
|
+
|
|
10
|
+
def list_accounts() -> Any:
|
|
11
|
+
"""Return all accounts with password state and masked sensitive fields."""
|
|
12
|
+
raise runtime_unavailable("list_accounts")
|
|
13
|
+
|
|
14
|
+
def list_account_summaries() -> Any:
|
|
15
|
+
"""Return account identity fields without loading large profile images."""
|
|
16
|
+
raise runtime_unavailable("list_account_summaries")
|
|
17
|
+
|
|
18
|
+
def get_account_summary(account_id: int) -> Any:
|
|
19
|
+
"""Return identity fields without loading profile images or account tokens."""
|
|
20
|
+
raise runtime_unavailable("get_account_summary")
|
|
21
|
+
|
|
22
|
+
def get_account(account_id: int) -> Any:
|
|
23
|
+
"""Return a full account record with masked account tokens, if it exists."""
|
|
24
|
+
raise runtime_unavailable("get_account")
|
|
25
|
+
|
|
26
|
+
def create_account(name: str, role: str, avatar_b64: str | None) -> Any:
|
|
27
|
+
"""Create an account and return the inserted account record."""
|
|
28
|
+
raise runtime_unavailable("create_account")
|
|
29
|
+
|
|
30
|
+
def update_account(account_id: int, name: str | None, role: str | None, avatar_b64: str | None, nickname: str | None = ..., about: str | None = ..., password: str | None = ..., old_password: str | None = ...) -> Any:
|
|
31
|
+
"""Update account profile fields, role, avatar, or password."""
|
|
32
|
+
raise runtime_unavailable("update_account")
|
|
33
|
+
|
|
34
|
+
def delete_profile_picture(account_id: int) -> bool:
|
|
35
|
+
"""Remove the profile picture for an account."""
|
|
36
|
+
raise runtime_unavailable("delete_profile_picture")
|
|
37
|
+
|
|
38
|
+
def delete_account(account_id: int, force: bool = ...) -> bool:
|
|
39
|
+
"""Delete an account, optionally bypassing last-admin protection."""
|
|
40
|
+
raise runtime_unavailable("delete_account")
|
|
41
|
+
|
|
42
|
+
def verify_account_password(account_id: int, password: str) -> str:
|
|
43
|
+
"""Return the password verification status for an account."""
|
|
44
|
+
raise runtime_unavailable("verify_account_password")
|
|
45
|
+
|
|
46
|
+
def create_account_token(account_id: int, password_protected: bool = ..., user_agent: str | None = ..., ip_address: str | None = ...) -> Any:
|
|
47
|
+
"""Create a persistent account token for an account."""
|
|
48
|
+
raise runtime_unavailable("create_account_token")
|
|
49
|
+
|
|
50
|
+
def revoke_token(account_id: int, token: str | None, revoke_all: bool = ...) -> Any:
|
|
51
|
+
"""Revoke one account token or all active tokens for an account."""
|
|
52
|
+
raise runtime_unavailable("revoke_token")
|
|
53
|
+
|
|
54
|
+
def delete_account_token(account_id: int, token: str) -> Any:
|
|
55
|
+
"""Permanently delete a revoked account token."""
|
|
56
|
+
raise runtime_unavailable("delete_account_token")
|
|
57
|
+
|
|
58
|
+
def create_2fa_setup(account_id: int) -> Any:
|
|
59
|
+
"""Create a two-factor authentication secret, QR code, and backup codes."""
|
|
60
|
+
raise runtime_unavailable("create_2fa_setup")
|
|
61
|
+
|
|
62
|
+
def verify_2fa_code(account_id: int, code: str, allow_enabled_bypass: bool = ..., backup_code: str | None = ...) -> Any:
|
|
63
|
+
"""Verify a two-factor authentication code or backup code for an account."""
|
|
64
|
+
raise runtime_unavailable("verify_2fa_code")
|
|
65
|
+
|
|
66
|
+
def delete_2fa(account_id: int, code: str) -> Any:
|
|
67
|
+
"""Disable two-factor authentication for an account after code verification."""
|
|
68
|
+
raise runtime_unavailable("delete_2fa")
|
|
69
|
+
|
|
70
|
+
def create_backup_codes(account_id: int) -> Any:
|
|
71
|
+
"""Create and store backup codes for account two-factor authentication."""
|
|
72
|
+
raise runtime_unavailable("create_backup_codes")
|
|
73
|
+
|
|
74
|
+
def delete_backup_codes(account_id: int) -> Any:
|
|
75
|
+
"""Delete all backup codes for an account."""
|
|
76
|
+
raise runtime_unavailable("delete_backup_codes")
|
|
77
|
+
|
|
78
|
+
def verify_backup_code(account_id: int, code: str) -> Any:
|
|
79
|
+
"""Verify and consume a two-factor authentication backup code."""
|
|
80
|
+
raise runtime_unavailable("verify_backup_code")
|
|
81
|
+
|
|
82
|
+
def has_backup_codes(account_id: int) -> Any:
|
|
83
|
+
"""Return whether an account has any backup codes available."""
|
|
84
|
+
raise runtime_unavailable("has_backup_codes")
|
|
85
|
+
|
|
86
|
+
__all__ = ['create_2fa_setup', 'create_account', 'create_account_token', 'create_backup_codes', 'delete_2fa', 'delete_account', 'delete_account_token', 'delete_backup_codes', 'delete_profile_picture', 'get_account', 'get_account_summary', 'has_backup_codes', 'list_account_summaries', 'list_accounts', 'revoke_token', 'update_account', 'verify_2fa_code', 'verify_account_password', 'verify_backup_code']
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `admin` helpers."""
|
|
9
|
+
|
|
10
|
+
def verify_admin(auth = ..., x_account_token: str = ...) -> bool:
|
|
11
|
+
"""Verify if an account has admin access based on account token."""
|
|
12
|
+
raise runtime_unavailable("verify_admin")
|
|
13
|
+
|
|
14
|
+
def get_admin_status(account_id: int) -> bool:
|
|
15
|
+
"""Return whether an account is an admin account based on account id."""
|
|
16
|
+
raise runtime_unavailable("get_admin_status")
|
|
17
|
+
|
|
18
|
+
__all__ = ['get_admin_status', 'verify_admin']
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Typed route decorators for OmniPlayr backend plugin API routes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Callable
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
RouteHandler = Callable[..., Any]
|
|
9
|
+
RouteDecorator = Callable[[RouteHandler], RouteHandler]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PluginApi:
|
|
13
|
+
"""Development-time facade for OmniPlayr backend plugin routes.
|
|
14
|
+
|
|
15
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/routes.html#registering-routes)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def route(self, method: str, path: str, **kwargs: Any) -> RouteDecorator:
|
|
19
|
+
"""Create a typed route decorator."""
|
|
20
|
+
|
|
21
|
+
def decorator(handler: RouteHandler) -> RouteHandler:
|
|
22
|
+
return handler
|
|
23
|
+
|
|
24
|
+
return decorator
|
|
25
|
+
|
|
26
|
+
def get(self, path: str, **kwargs: Any) -> RouteDecorator:
|
|
27
|
+
"""Decorate a GET route for a backend plugin."""
|
|
28
|
+
|
|
29
|
+
return self.route("GET", path, **kwargs)
|
|
30
|
+
|
|
31
|
+
def post(self, path: str, **kwargs: Any) -> RouteDecorator:
|
|
32
|
+
"""Decorate a POST route for a backend plugin."""
|
|
33
|
+
|
|
34
|
+
return self.route("POST", path, **kwargs)
|
|
35
|
+
|
|
36
|
+
def put(self, path: str, **kwargs: Any) -> RouteDecorator:
|
|
37
|
+
"""Decorate a PUT route for a backend plugin."""
|
|
38
|
+
|
|
39
|
+
return self.route("PUT", path, **kwargs)
|
|
40
|
+
|
|
41
|
+
def patch(self, path: str, **kwargs: Any) -> RouteDecorator:
|
|
42
|
+
"""Decorate a PATCH route for a backend plugin."""
|
|
43
|
+
|
|
44
|
+
return self.route("PATCH", path, **kwargs)
|
|
45
|
+
|
|
46
|
+
def delete(self, path: str, **kwargs: Any) -> RouteDecorator:
|
|
47
|
+
"""Decorate a DELETE route for a backend plugin."""
|
|
48
|
+
|
|
49
|
+
return self.route("DELETE", path, **kwargs)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
api = PluginApi()
|
|
53
|
+
|
|
54
|
+
__all__ = ["PluginApi", "RouteDecorator", "RouteHandler", "api"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `backend_config` helpers."""
|
|
9
|
+
|
|
10
|
+
def load_configs() -> Any:
|
|
11
|
+
"""Load and validate backend configuration files from disk."""
|
|
12
|
+
raise runtime_unavailable("load_configs")
|
|
13
|
+
|
|
14
|
+
def get_config(key_path, default = ...) -> Any:
|
|
15
|
+
"""Return a backend configuration value by dotted key path."""
|
|
16
|
+
raise runtime_unavailable("get_config")
|
|
17
|
+
|
|
18
|
+
def flatten_configs() -> Any:
|
|
19
|
+
"""Return flattened backend config metadata for UI rendering."""
|
|
20
|
+
raise runtime_unavailable("flatten_configs")
|
|
21
|
+
|
|
22
|
+
def flatten_frontend_configs() -> Any:
|
|
23
|
+
"""Return flattened frontend config metadata for UI rendering."""
|
|
24
|
+
raise runtime_unavailable("flatten_frontend_configs")
|
|
25
|
+
|
|
26
|
+
__all__ = ['flatten_configs', 'flatten_frontend_configs', 'get_config', 'load_configs']
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `config` helpers."""
|
|
9
|
+
|
|
10
|
+
def get_plugin_config(plugin_key: str, key_path: str, default = ...) -> Any:
|
|
11
|
+
"""Return a plugin configuration value by dotted key path."""
|
|
12
|
+
raise runtime_unavailable("get_plugin_config")
|
|
13
|
+
|
|
14
|
+
def reload_plugin_config(plugin_key: str) -> Any:
|
|
15
|
+
"""Clear and reload cached configuration for a plugin."""
|
|
16
|
+
raise runtime_unavailable("reload_plugin_config")
|
|
17
|
+
|
|
18
|
+
def flatten_plugin_configs(plugin_key: str) -> Any:
|
|
19
|
+
"""Return flattened plugin config metadata for UI rendering."""
|
|
20
|
+
raise runtime_unavailable("flatten_plugin_configs")
|
|
21
|
+
|
|
22
|
+
__all__ = ['flatten_plugin_configs', 'get_plugin_config', 'reload_plugin_config']
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `db` helpers."""
|
|
9
|
+
|
|
10
|
+
ProtectionLevel = Literal['read', 'write']
|
|
11
|
+
|
|
12
|
+
PROTECTED_TABLES: dict[str, ProtectionLevel] = {'accounts': 'write', 'server': 'read', 'setup_state': 'read', 'access_tokens': 'read', 'account_tokens': 'read', 'notifications': 'write', 'initial_notifications_sent': 'read', 'update_cache': 'read', 'backup_codes': 'read'}
|
|
13
|
+
|
|
14
|
+
def set_table_protection(table: str, level: ProtectionLevel) -> None:
|
|
15
|
+
"""Set the plugin access protection level for a database table."""
|
|
16
|
+
raise runtime_unavailable("set_table_protection")
|
|
17
|
+
|
|
18
|
+
def remove_table_protection(table: str) -> None:
|
|
19
|
+
"""Remove plugin access protection from a database table."""
|
|
20
|
+
raise runtime_unavailable("remove_table_protection")
|
|
21
|
+
|
|
22
|
+
class PluginDB:
|
|
23
|
+
"""Plugin-scoped database helper enforcing table grants and protections."""
|
|
24
|
+
|
|
25
|
+
def fetch(self, table: str, where: dict[str, Any] | None = ..., columns: list[str] | None = ..., order_by: str | None = ..., limit: int | None = ...) -> list[dict]:
|
|
26
|
+
"""Fetch rows from an accessible table with optional filtering and ordering."""
|
|
27
|
+
raise runtime_unavailable("fetch")
|
|
28
|
+
|
|
29
|
+
def fetch_one(self, table: str, where: dict[str, Any], columns: list[str] | None = ...) -> dict | None:
|
|
30
|
+
"""Fetch the first row matching a table filter."""
|
|
31
|
+
raise runtime_unavailable("fetch_one")
|
|
32
|
+
|
|
33
|
+
def insert(self, table: str, data: dict[str, Any]) -> dict:
|
|
34
|
+
"""Insert a row into a writable table and return the inserted row."""
|
|
35
|
+
raise runtime_unavailable("insert")
|
|
36
|
+
|
|
37
|
+
def update(self, table: str, data: dict[str, Any], where: dict[str, Any]) -> int:
|
|
38
|
+
"""Update rows in a writable table and return the affected row count."""
|
|
39
|
+
raise runtime_unavailable("update")
|
|
40
|
+
|
|
41
|
+
def delete(self, table: str, where: dict[str, Any]) -> int:
|
|
42
|
+
"""Delete rows from a writable table and return the affected row count."""
|
|
43
|
+
raise runtime_unavailable("delete")
|
|
44
|
+
|
|
45
|
+
def count(self, table: str, where: dict[str, Any] | None = ...) -> int:
|
|
46
|
+
"""Count rows in an accessible table with an optional filter."""
|
|
47
|
+
raise runtime_unavailable("count")
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def accessible_tables(self) -> dict[str, str]:
|
|
51
|
+
"""Return the table grants available to this plugin."""
|
|
52
|
+
raise runtime_unavailable("accessible_tables")
|
|
53
|
+
|
|
54
|
+
def request_db_access(plugin_key: str, *, own: dict[str, dict[str, str]] | None = ..., read: list[str] | None = ..., readwrite: list[str] | None = ...) -> PluginDB:
|
|
55
|
+
"""Request database table grants for a backend plugin."""
|
|
56
|
+
raise runtime_unavailable("request_db_access")
|
|
57
|
+
|
|
58
|
+
__all__ = ['PROTECTED_TABLES', 'PluginDB', 'ProtectionLevel', 'remove_table_protection', 'request_db_access', 'set_table_protection']
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `diagnostics` helpers."""
|
|
9
|
+
|
|
10
|
+
def record_error(level: str) -> None:
|
|
11
|
+
"""Increment the diagnostic error counter for a severity level."""
|
|
12
|
+
raise runtime_unavailable("record_error")
|
|
13
|
+
|
|
14
|
+
def get_error_counts() -> dict:
|
|
15
|
+
"""Return current diagnostic error counters."""
|
|
16
|
+
raise runtime_unavailable("get_error_counts")
|
|
17
|
+
|
|
18
|
+
def get_uptime_seconds() -> float:
|
|
19
|
+
"""Return backend process uptime in seconds."""
|
|
20
|
+
raise runtime_unavailable("get_uptime_seconds")
|
|
21
|
+
|
|
22
|
+
def reset_error_counts() -> None:
|
|
23
|
+
"""Reset all diagnostic error counters to zero."""
|
|
24
|
+
raise runtime_unavailable("reset_error_counts")
|
|
25
|
+
|
|
26
|
+
def run_diagnostics() -> None:
|
|
27
|
+
"""Run one diagnostic pass over system health signals."""
|
|
28
|
+
raise runtime_unavailable("run_diagnostics")
|
|
29
|
+
|
|
30
|
+
def start_diagnostics(interval_seconds: int = ...) -> None:
|
|
31
|
+
"""Start background diagnostic and event-loop lag monitors."""
|
|
32
|
+
raise runtime_unavailable("start_diagnostics")
|
|
33
|
+
|
|
34
|
+
__all__ = ['get_error_counts', 'get_uptime_seconds', 'record_error', 'reset_error_counts', 'run_diagnostics', 'start_diagnostics']
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `functions` helpers."""
|
|
9
|
+
|
|
10
|
+
class PluginNotAvailableError(LookupError):
|
|
11
|
+
"""
|
|
12
|
+
Raised when a cross-plugin call targets a plugin that is not loaded.
|
|
13
|
+
|
|
14
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#handling-unavailable-functions)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
class PluginFunctionNotFoundError(LookupError):
|
|
18
|
+
"""
|
|
19
|
+
Raised when a loaded plugin does not expose the requested function.
|
|
20
|
+
|
|
21
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#handling-unavailable-functions)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
class PluginFunctions:
|
|
25
|
+
"""Plugin-scoped helper for exposing and calling cross-plugin functions."""
|
|
26
|
+
|
|
27
|
+
def expose(self, function_name: str, function: Callable[..., Any] | None = ...) -> Any:
|
|
28
|
+
"""Expose a plugin-local callable for other backend plugins."""
|
|
29
|
+
raise runtime_unavailable("expose")
|
|
30
|
+
|
|
31
|
+
def call(self, plugin_key: str, function_name: str, *args: Any, **kwargs: Any) -> Any:
|
|
32
|
+
"""Call a function exposed by another backend plugin."""
|
|
33
|
+
raise runtime_unavailable("call")
|
|
34
|
+
|
|
35
|
+
def is_installed(self, plugin_key: str) -> bool:
|
|
36
|
+
"""Return whether another backend plugin has been loaded."""
|
|
37
|
+
raise runtime_unavailable("is_installed")
|
|
38
|
+
|
|
39
|
+
def has_function(self, plugin_key: str, function_name: str) -> bool:
|
|
40
|
+
"""Return whether another plugin exposes a named function."""
|
|
41
|
+
raise runtime_unavailable("has_function")
|
|
42
|
+
|
|
43
|
+
def expose(plugin_key: str, function_name: str, function: Callable[..., Any]) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Expose a callable under a plugin key for cross-plugin calls.
|
|
46
|
+
|
|
47
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#exposing-a-function)
|
|
48
|
+
"""
|
|
49
|
+
raise runtime_unavailable("expose")
|
|
50
|
+
|
|
51
|
+
def mark_plugin_loaded(plugin_key: str) -> None:
|
|
52
|
+
"""Mark a plugin as loaded in the in-memory cross-plugin registry."""
|
|
53
|
+
raise runtime_unavailable("mark_plugin_loaded")
|
|
54
|
+
|
|
55
|
+
def remove_plugin(plugin_key: str) -> None:
|
|
56
|
+
"""Remove a plugin and its exposed functions from the registry."""
|
|
57
|
+
raise runtime_unavailable("remove_plugin")
|
|
58
|
+
|
|
59
|
+
def is_installed(plugin_key: str) -> bool:
|
|
60
|
+
"""
|
|
61
|
+
Return whether a plugin has been marked as loaded.
|
|
62
|
+
|
|
63
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#available-helpers)
|
|
64
|
+
"""
|
|
65
|
+
raise runtime_unavailable("is_installed")
|
|
66
|
+
|
|
67
|
+
def has_function(plugin_key: str, function_name: str) -> bool:
|
|
68
|
+
"""
|
|
69
|
+
Return whether a loaded plugin exposes a named function.
|
|
70
|
+
|
|
71
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#available-helpers)
|
|
72
|
+
"""
|
|
73
|
+
raise runtime_unavailable("has_function")
|
|
74
|
+
|
|
75
|
+
def call(plugin_key: str, function_name: str, *args: Any, **kwargs: Any) -> Any:
|
|
76
|
+
"""
|
|
77
|
+
Call a function exposed by another backend plugin.
|
|
78
|
+
|
|
79
|
+
[View Documentation](https://omniplayr.wokki20.nl/docs/plugins/building/backend/cross-plugin-functions.html#discovering-and-calling-functions)
|
|
80
|
+
"""
|
|
81
|
+
raise runtime_unavailable("call")
|
|
82
|
+
|
|
83
|
+
__all__ = ['PluginFunctionNotFoundError', 'PluginFunctions', 'PluginNotAvailableError', 'call', 'expose', 'has_function', 'is_installed', 'mark_plugin_loaded', 'remove_plugin']
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `health` helpers."""
|
|
9
|
+
|
|
10
|
+
class ServiceStatus:
|
|
11
|
+
"""Health model describing one backend-related service or container."""
|
|
12
|
+
name: str
|
|
13
|
+
id: str
|
|
14
|
+
status: str
|
|
15
|
+
running: bool
|
|
16
|
+
healthy: bool
|
|
17
|
+
|
|
18
|
+
class HealthResponse:
|
|
19
|
+
"""Health response model returned by the backend health endpoint."""
|
|
20
|
+
status: str
|
|
21
|
+
uptime_seconds: float
|
|
22
|
+
minor_health_error: int
|
|
23
|
+
normal_health_error: int
|
|
24
|
+
critical_health_error: int
|
|
25
|
+
services: list[ServiceStatus]
|
|
26
|
+
|
|
27
|
+
def health() -> HealthResponse:
|
|
28
|
+
"""Return overall backend health, uptime, diagnostics, and service status."""
|
|
29
|
+
raise runtime_unavailable("health")
|
|
30
|
+
|
|
31
|
+
__all__ = ['HealthResponse', 'ServiceStatus', 'health']
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `installer` helpers."""
|
|
9
|
+
|
|
10
|
+
def fetch_plugin_info(package_id: str) -> dict | None:
|
|
11
|
+
"""Fetch plugin registry metadata for a package id."""
|
|
12
|
+
raise runtime_unavailable("fetch_plugin_info")
|
|
13
|
+
|
|
14
|
+
def install_local_plugin(source_path: str, target: str, package_id: str | None = ..., mode: str = ...) -> dict:
|
|
15
|
+
"""Register or link a local plugin during development mode."""
|
|
16
|
+
raise runtime_unavailable("install_local_plugin")
|
|
17
|
+
|
|
18
|
+
def install_plugin(package_id: str, version: str | None, target: str | None) -> dict:
|
|
19
|
+
"""Download and install a plugin from the configured registry."""
|
|
20
|
+
raise runtime_unavailable("install_plugin")
|
|
21
|
+
|
|
22
|
+
__all__ = ['fetch_plugin_info', 'install_local_plugin', 'install_plugin']
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `logging` helpers."""
|
|
9
|
+
|
|
10
|
+
LEVEL_COLORS = {'debug': '\x1b[38;5;244m', 'info': '\x1b[38;5;117m', 'success': '\x1b[38;5;82m', 'warning': '\x1b[38;5;214m', 'warn': '\x1b[38;5;214m', 'error': '\x1b[38;5;196m', 'critical': '\x1b[38;5;201m', 'diag': '\x1b[38;5;51m', 'warning_diagnostic': '\x1b[38;5;220m', 'error_diagnostic': '\x1b[38;5;208m', 'critical_diagnostic': '\x1b[38;5;199m'}
|
|
11
|
+
|
|
12
|
+
RESET = '\x1b[0m'
|
|
13
|
+
|
|
14
|
+
BOLD = '\x1b[1m'
|
|
15
|
+
|
|
16
|
+
DIM = '\x1b[2m'
|
|
17
|
+
|
|
18
|
+
LEVEL_LABELS = {'debug': 'DBG', 'info': 'INF', 'success': 'SUC', 'warning': 'WRN', 'warn': 'WRN', 'error': 'ERR', 'critical': 'CRT', 'diag': 'DIG', 'warning_diagnostic': 'WDG', 'error_diagnostic': 'EDG', 'critical_diagnostic': 'CDG'}
|
|
19
|
+
|
|
20
|
+
def log(message: str, level: str = ..., source: str | None = ...) -> None:
|
|
21
|
+
"""Write a structured OmniPlayr log message to console and log files."""
|
|
22
|
+
raise runtime_unavailable("log")
|
|
23
|
+
|
|
24
|
+
def log_exception(exc: Exception, message: str = ..., source: str | None = ...) -> None:
|
|
25
|
+
"""Log an exception with optional context and traceback information."""
|
|
26
|
+
raise runtime_unavailable("log_exception")
|
|
27
|
+
|
|
28
|
+
def setup_exception_hook() -> None:
|
|
29
|
+
"""Install a process-wide hook for uncaught exceptions."""
|
|
30
|
+
raise runtime_unavailable("setup_exception_hook")
|
|
31
|
+
|
|
32
|
+
def setup_thread_exception_hook() -> None:
|
|
33
|
+
"""Install a hook for uncaught exceptions in Python threads."""
|
|
34
|
+
raise runtime_unavailable("setup_thread_exception_hook")
|
|
35
|
+
|
|
36
|
+
def setup_asyncio_exception_handler(loop: asyncio.AbstractEventLoop) -> None:
|
|
37
|
+
"""Install an asyncio exception handler on an event loop."""
|
|
38
|
+
raise runtime_unavailable("setup_asyncio_exception_handler")
|
|
39
|
+
|
|
40
|
+
def get_logs(since_hours: int = ..., limit: int = ..., before: str | None = ..., since: str | None = ...) -> dict:
|
|
41
|
+
"""Return recent parsed log entries with basic pagination support."""
|
|
42
|
+
raise runtime_unavailable("get_logs")
|
|
43
|
+
|
|
44
|
+
__all__ = ['BOLD', 'DIM', 'LEVEL_COLORS', 'LEVEL_LABELS', 'RESET', 'get_logs', 'log', 'log_exception', 'setup_asyncio_exception_handler', 'setup_exception_hook', 'setup_thread_exception_hook']
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `notifications` helpers."""
|
|
9
|
+
|
|
10
|
+
INITIAL_NOTIFICATIONS: list[dict] = [{'key': 'welcome_docs', 'icon': 'BookOpenText', 'title': 'Need some help?', 'text': 'You can always read the documentation for OmniPlayr on our website.', 'action_type': 'external', 'action_url': 'https://omniplayr.wokki20.nl/docs/'}, {'key': 'welcome_message', 'icon': 'PartyPopper', 'title': 'Welcome to OmniPlayr', 'text': 'Thanks for using OmniPlayr <link href="https://omniplayr.wokki20.nl">{version}</link>!', 'action_type': None, 'action_url': None}]
|
|
11
|
+
|
|
12
|
+
class NotificationManager:
|
|
13
|
+
"""Manage active notification websocket connections by account."""
|
|
14
|
+
|
|
15
|
+
async def connect(self, account_id: int, ws: WebSocket) -> Any:
|
|
16
|
+
"""Accept and register a websocket connection for an account."""
|
|
17
|
+
raise runtime_unavailable("connect")
|
|
18
|
+
|
|
19
|
+
def disconnect(self, account_id: int, ws: WebSocket) -> Any:
|
|
20
|
+
"""Remove a websocket connection for an account."""
|
|
21
|
+
raise runtime_unavailable("disconnect")
|
|
22
|
+
|
|
23
|
+
async def send_to_user(self, account_id: int, data: dict) -> Any:
|
|
24
|
+
"""Send a JSON payload to every active websocket for an account."""
|
|
25
|
+
raise runtime_unavailable("send_to_user")
|
|
26
|
+
|
|
27
|
+
def get_notifications(account_id: int) -> list[dict]:
|
|
28
|
+
"""Return notifications for an account ordered from newest to oldest."""
|
|
29
|
+
raise runtime_unavailable("get_notifications")
|
|
30
|
+
|
|
31
|
+
def get_unread_count(account_id: int) -> int:
|
|
32
|
+
"""Return the unread notification count for an account."""
|
|
33
|
+
raise runtime_unavailable("get_unread_count")
|
|
34
|
+
|
|
35
|
+
def mark_read(notification_id: int, account_id: int) -> bool:
|
|
36
|
+
"""Mark one notification as read for an account."""
|
|
37
|
+
raise runtime_unavailable("mark_read")
|
|
38
|
+
|
|
39
|
+
def delete_notification(notification_id: int, account_id: int) -> bool:
|
|
40
|
+
"""Delete one notification for an account."""
|
|
41
|
+
raise runtime_unavailable("delete_notification")
|
|
42
|
+
|
|
43
|
+
async def notify(account_id: int, icon: str, title: str, text: str, action_type: str | None = ..., action_url: str | None = ...) -> dict:
|
|
44
|
+
"""Create a notification and push it to active account websockets."""
|
|
45
|
+
raise runtime_unavailable("notify")
|
|
46
|
+
|
|
47
|
+
async def notify_once(account_id: int, notification_key: str, icon: str, title: str, text: str, action_type: str | None = ..., action_url: str | None = ...) -> dict | None:
|
|
48
|
+
"""Create a keyed notification only if it has not been sent before."""
|
|
49
|
+
raise runtime_unavailable("notify_once")
|
|
50
|
+
|
|
51
|
+
def set_main_loop(loop: asyncio.AbstractEventLoop) -> None:
|
|
52
|
+
"""Store the main asyncio event loop for synchronous notification helpers."""
|
|
53
|
+
raise runtime_unavailable("set_main_loop")
|
|
54
|
+
|
|
55
|
+
def notify_sync(account_id: int, icon: str, title: str, text: str, action_type: str | None = ..., action_url: str | None = ...) -> None:
|
|
56
|
+
"""Schedule or run notification delivery from synchronous code."""
|
|
57
|
+
raise runtime_unavailable("notify_sync")
|
|
58
|
+
|
|
59
|
+
def notify_once_sync(account_id: int, notification_key: str, icon: str, title: str, text: str, action_type: str | None = ..., action_url: str | None = ...) -> None:
|
|
60
|
+
"""Schedule or run keyed notification delivery from synchronous code."""
|
|
61
|
+
raise runtime_unavailable("notify_once_sync")
|
|
62
|
+
|
|
63
|
+
__all__ = ['INITIAL_NOTIFICATIONS', 'NotificationManager', 'delete_notification', 'get_notifications', 'get_unread_count', 'mark_read', 'notify', 'notify_once', 'notify_once_sync', 'notify_sync', 'set_main_loop']
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `passwords` helpers."""
|
|
9
|
+
|
|
10
|
+
def password_hash(password: str) -> str:
|
|
11
|
+
"""Hash a plaintext password for storage."""
|
|
12
|
+
raise runtime_unavailable("password_hash")
|
|
13
|
+
|
|
14
|
+
def password_check(password: str, hash: str) -> bool:
|
|
15
|
+
"""Return whether a plaintext password matches a stored password hash."""
|
|
16
|
+
raise runtime_unavailable("password_check")
|
|
17
|
+
|
|
18
|
+
__all__ = ['password_check', 'password_hash']
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `runtime` helpers."""
|
|
9
|
+
|
|
10
|
+
class PluginBase:
|
|
11
|
+
"""Base class for backend playback source plugins."""
|
|
12
|
+
source_type: str = ''
|
|
13
|
+
|
|
14
|
+
def get_stream(self, song_id: str, account_id: int) -> Any:
|
|
15
|
+
"""Return a stream or file-like object for a song and account."""
|
|
16
|
+
raise runtime_unavailable("get_stream")
|
|
17
|
+
|
|
18
|
+
def get_content_type(self, song_id: str, account_id: int) -> str:
|
|
19
|
+
"""Return the MIME type for a song stream."""
|
|
20
|
+
raise runtime_unavailable("get_content_type")
|
|
21
|
+
|
|
22
|
+
def get_file_size(self, song_id: str, account_id: int) -> int | None:
|
|
23
|
+
"""Return the byte size for a song stream, if known."""
|
|
24
|
+
raise runtime_unavailable("get_file_size")
|
|
25
|
+
|
|
26
|
+
def get_metadata(self, song_id: str, account_id: int) -> dict:
|
|
27
|
+
"""Return metadata for a song visible to the given account."""
|
|
28
|
+
raise runtime_unavailable("get_metadata")
|
|
29
|
+
|
|
30
|
+
def check_ownership(self, song_id: str, account_id: int) -> bool:
|
|
31
|
+
"""Return whether the given account may access the song."""
|
|
32
|
+
raise runtime_unavailable("check_ownership")
|
|
33
|
+
|
|
34
|
+
def register(plugin: PluginBase) -> Any:
|
|
35
|
+
"""Register a backend playback source plugin instance."""
|
|
36
|
+
raise runtime_unavailable("register")
|
|
37
|
+
|
|
38
|
+
def get_plugin(source_type: str) -> PluginBase | None:
|
|
39
|
+
"""Return the registered plugin for a source type, if any."""
|
|
40
|
+
raise runtime_unavailable("get_plugin")
|
|
41
|
+
|
|
42
|
+
def get_plugin_router() -> APIRouter:
|
|
43
|
+
"""Return the shared FastAPI router used for plugin routes."""
|
|
44
|
+
raise runtime_unavailable("get_plugin_router")
|
|
45
|
+
|
|
46
|
+
def get_backend_plugin_dir(plugin_key: str, plugin_spec: Any = ...) -> Path:
|
|
47
|
+
"""Return the filesystem directory for a backend plugin key."""
|
|
48
|
+
raise runtime_unavailable("get_backend_plugin_dir")
|
|
49
|
+
|
|
50
|
+
def load_plugins() -> Any:
|
|
51
|
+
"""Load configured backend plugins into the current server process."""
|
|
52
|
+
raise runtime_unavailable("load_plugins")
|
|
53
|
+
|
|
54
|
+
__all__ = ['PluginBase', 'get_backend_plugin_dir', 'get_plugin', 'get_plugin_router', 'load_plugins', 'register']
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `server` helpers."""
|
|
9
|
+
|
|
10
|
+
def parse_interval(interval_str: str) -> relativedelta:
|
|
11
|
+
"""Parse a human interval string into a timedelta or relativedelta."""
|
|
12
|
+
raise runtime_unavailable("parse_interval")
|
|
13
|
+
|
|
14
|
+
def verify_token(access_token: str) -> Any:
|
|
15
|
+
"""Validate an access token and return the stored token value."""
|
|
16
|
+
raise runtime_unavailable("verify_token")
|
|
17
|
+
|
|
18
|
+
def verify_auth(creds: HTTPAuthorizationCredentials = ...) -> Any:
|
|
19
|
+
"""Validate FastAPI bearer credentials for an authenticated request."""
|
|
20
|
+
raise runtime_unavailable("verify_auth")
|
|
21
|
+
|
|
22
|
+
def match_account(account_id: int, account_token: str, allow_admin_force: bool = ...) -> bool:
|
|
23
|
+
"""Return whether an account token belongs to an account or allowed admin."""
|
|
24
|
+
raise runtime_unavailable("match_account")
|
|
25
|
+
|
|
26
|
+
def get_token_user(token: str) -> Any:
|
|
27
|
+
"""Return the account id associated with an active account token."""
|
|
28
|
+
raise runtime_unavailable("get_token_user")
|
|
29
|
+
|
|
30
|
+
async def create_access_token(password_protected: bool, cur: object, only_access_token: bool = ...) -> dict:
|
|
31
|
+
"""Create access and refresh tokens using configured token lifetimes."""
|
|
32
|
+
raise runtime_unavailable("create_access_token")
|
|
33
|
+
|
|
34
|
+
__all__ = ['create_access_token', 'get_token_user', 'match_account', 'parse_interval', 'verify_auth', 'verify_token']
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# This file is generated from the OmniPlayr server backend.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Callable, Literal
|
|
5
|
+
|
|
6
|
+
from ._runtime import runtime_unavailable
|
|
7
|
+
|
|
8
|
+
"""Generated SDK stubs for OmniPlayr backend `updater` helpers."""
|
|
9
|
+
|
|
10
|
+
ROOT_PRESERVED = {'backend', 'frontend', '.git', '.github', '.gitignore', '.gitattributes', 'README.md', 'docker-compose.yml', 'db', 'logs', 'user_storage', '.env'}
|
|
11
|
+
|
|
12
|
+
BACKEND_PRESERVED = {'plugins', 'config', 'config.local.json', 'logs', '.safe_mode'}
|
|
13
|
+
|
|
14
|
+
FRONTEND_PRESERVED = {}
|
|
15
|
+
|
|
16
|
+
def check_for_updates(force: bool = ...) -> dict:
|
|
17
|
+
"""Check GitHub for available backend or frontend updates."""
|
|
18
|
+
raise runtime_unavailable("check_for_updates")
|
|
19
|
+
|
|
20
|
+
def apply_update() -> dict:
|
|
21
|
+
"""Download and apply the latest available OmniPlayr update."""
|
|
22
|
+
raise runtime_unavailable("apply_update")
|
|
23
|
+
|
|
24
|
+
__all__ = ['BACKEND_PRESERVED', 'FRONTEND_PRESERVED', 'ROOT_PRESERVED', 'apply_update', 'check_for_updates']
|