68 lines
3.7 KiB
Markdown
68 lines
3.7 KiB
Markdown
# Plugins
|
|
|
|
This folder is the primary home for bundled plugins and also the default search
|
|
path for drop-in plugins.
|
|
|
|
User-facing docs and CLI flows treat these integrations as plugins. Some Python
|
|
types and some stored config keys still use older `Provider` naming internally,
|
|
but that is a legacy implementation detail rather than the preferred public
|
|
term.
|
|
|
|
Preferred layout:
|
|
- Put each plugin in its own folder under `plugins/<name>/` with an `__init__.py`.
|
|
- Keep plugin-specific assets beside the code in that same folder.
|
|
- Single-file `.py` plugins are still supported, but package folders are the
|
|
recommended plug-and-play format.
|
|
|
|
That means a plugin can ship as a drag-and-drop folder with extras such as:
|
|
- `cookies.txt`
|
|
- templates or fixture files
|
|
- helper modules
|
|
- small static assets
|
|
|
|
Built-in bundled plugins use the same layout as external plugins. Additional
|
|
drop-in plugin search paths are:
|
|
- `plugins/` in the repo root
|
|
- `plugins/` in the current working directory
|
|
- Any directory listed in `MM_PLUGIN_PATH`
|
|
- Any directory listed in `MEDEIA_PLUGIN_PATH`
|
|
|
|
Plugin rules:
|
|
- A plugin can be a single `.py` file or a package directory with `__init__.py`.
|
|
- Current plugin classes inherit from `PluginCore.base.Provider`.
|
|
- Give the plugin a stable name using `PLUGIN_NAME` or the class name.
|
|
|
|
Example skeleton:
|
|
|
|
```python
|
|
from PluginCore.base import Provider, SearchResult
|
|
|
|
|
|
class MyPlugin(Provider):
|
|
PLUGIN_NAME = "myplugin"
|
|
URL_DOMAINS = ("example.com",)
|
|
|
|
def search(self, query, limit=50, filters=None, **kwargs):
|
|
text = str(query or "").strip()
|
|
if not text:
|
|
return []
|
|
return [
|
|
SearchResult(
|
|
table="myplugin",
|
|
title=f"Result for {text}",
|
|
path=f"https://example.com/{text}",
|
|
)
|
|
]
|
|
```
|
|
|
|
Bundled walkthrough:
|
|
|
|
- Plugins can expose named config instances. The current stored config may still
|
|
use legacy key paths such as `provider.<plugin>.<instance>`, and cmdlets target
|
|
instances with `-instance <name>`.
|
|
- Use `.config plugins` in the CLI to browse configured plugin instances.
|
|
- The repo now includes a real FTP example plugin in [plugins/ftp/__init__.py](plugins/ftp/__init__.py).
|
|
- The walkthrough is in [docs/ftp_plugin_tutorial.md](docs/ftp_plugin_tutorial.md) and shows `search-file -plugin ftp -instance <name>`, folder drill-in via `@N`, file download routing, `@N | add-file -instance ...`, and `add-file -plugin ftp -instance <name>` uploads.
|
|
- The repo also includes an SCP example plugin in [plugins/scp/__init__.py](plugins/scp/__init__.py).
|
|
- The walkthrough is in [docs/scp_plugin_tutorial.md](docs/scp_plugin_tutorial.md) and shows `search-file -plugin scp -instance <name>`, SSH-backed directory drill-in, file download routing, `@N | add-file -instance ...`, and `add-file -plugin scp -instance <name>` uploads.
|
|
- The repo also includes a built-in HydrusNetwork plugin in [plugins/hydrusnetwork/__init__.py](plugins/hydrusnetwork/__init__.py). Its Hydrus client API now lives in the plugin-owned package [plugins/hydrusnetwork/api/__init__.py](plugins/hydrusnetwork/api/__init__.py), its configured-backend adapter lives in [plugins/hydrusnetwork/store_proxy.py](plugins/hydrusnetwork/store_proxy.py), and its heavy internal operations live in [plugins/hydrusnetwork/store_backend.py](plugins/hydrusnetwork/store_backend.py). This `plugins/<name>/api/` package shape is the intended pattern for plugin-owned API helpers going forward. The plugin resolves configured Hydrus instances directly from plugin config instead of routing back through `PluginCore.backend_registry`; the proxy exists only so generic backend callers can still target configured Hydrus instances. |