Files
Medios-Macina/plugins
2026-05-04 15:58:24 -07:00
..
2026-04-26 15:08:35 -07:00
2026-04-26 15:08:35 -07:00
2026-05-04 15:58:24 -07:00
2026-04-26 15:08:35 -07:00
2026-04-30 18:56:22 -07:00
2026-04-26 16:49:23 -07:00
2026-04-30 18:56:22 -07:00
2026-05-03 21:20:05 -07:00
2026-04-30 18:56:22 -07:00
2026-04-30 18:56:22 -07:00
2026-04-26 15:08:35 -07:00
2026-05-03 21:20:05 -07:00
2026-04-26 15:08:35 -07:00
2026-04-26 15:08:35 -07:00
2026-04-26 16:49:23 -07:00
2026-05-03 21:20:05 -07:00
2026-05-03 21:20:05 -07:00

Plugins

This folder is the primary home for bundled plugins and also the default search path for drop-in plugins.

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.
  • Define a class that inherits from ProviderCore.base.Provider.
  • Give it a stable name using PLUGIN_NAME or the class name.

Example skeleton:

from ProviderCore.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:

  • Providers can now expose named config instances under provider.<plugin>.<instance> and cmdlets can target them with -instance <name>.
  • The repo now includes a real FTP example plugin in plugins/ftp/__init__.py.
  • The walkthrough is in 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.
  • The walkthrough is in 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 now also includes a built-in HydrusNetwork provider in plugins/hydrusnetwork/__init__.py. Its Hydrus client API now lives in the plugin-owned package plugins/hydrusnetwork/api/__init__.py, its registry-facing store adapter lives in plugins/hydrusnetwork/store_proxy.py, and its heavy internal operations live in plugins/hydrusnetwork/store_backend.py. This plugins/<name>/api/ package shape is the intended pattern for plugin-owned API helpers going forward. The provider now resolves configured Hydrus instances directly from plugin config instead of routing back through Store.registry; the proxy exists only so generic store callers can still target configured Hydrus stores. API/HydrusNetwork.py and Store/HydrusNetwork.py are legacy compatibility shims only, and store discovery prefers the plugin-owned Hydrus hook over those shims.