# SPDX-License-Identifier: AGPL-3.0-or-later """.. sidebar:: Further reading .. - :ref:`plugins admin` - :ref:`SearXNG settings ` Plugins can extend or replace functionality of various components of SearXNG. Entry points (hooks) define when a plugin runs. Right now only three hooks are implemented. So feel free to implement a hook if it fits the behaviour of your plugin / a plugin doesn't need to implement all the hooks. - pre search: :py:obj:`Plugin.pre_search` - post search: :py:obj:`Plugin.post_search` - on each result item: :py:obj:`Plugin.on_result` Below you will find some examples, for more coding examples have a look at the built-in plugins :origin:`searx/plugins/` or `Only show green hosted results`_. .. _Only show green hosted results: https://github.com/return42/tgwf-searx-plugins/ Add Answer example ================== Here is an example of a very simple plugin that adds a "Hello World" into the answer area: In ``searx/plugins`` create a file named ``hello_world.py`` with the following content: .. code:: python from flask_babel import gettext as _ from searx.plugins import Plugin, PluginInfo from searx.result_types import Answer class MyPlugin(Plugin): id = "hello world" def __init__(self, plg_cfg): super().__init__(plg_cfg) self.info = PluginInfo(id=self.id, name=_("Hello"), description=_("demo plugin")) def post_search(self, request, search): return [ Answer(answer="Hello World") ] You will then need to add your new plugin in the :ref:`settings.yml` file like this: .. code:: yaml plugins: ... searx.plugins.hello_world.MyPlugin: active: true ``searx.plugins.hello_world.MyPlugin`` is the Python import path of the new plugin we created. ``searx.plugins.hello_world`` represents the file path, while ``MyPlugin`` represents the name of the plugin class. If you don't want the plugin to be part of SearXNG's core (i.e. maintain it independently of SearXNG), you may also place the file at any other path as long as you update the reference to it in :ref:`settings.yml`. For more examples, see :ref:`settings external_plugins`. .. _filter urls example: Filter URLs example =================== .. sidebar:: Further reading .. - :py:obj:`Result.filter_urls(..) ` The :py:obj:`Result.filter_urls(..) ` can be used to filter and/or modify URL fields. In the following example, the filter function ``my_url_filter``: .. code:: python def my_url_filter(result, field_name, url_src) -> bool | str: if "google" in url_src: return False # remove URL field from result if "facebook" in url_src: new_url = url_src.replace("facebook", "fb-dummy") return new_url # return modified URL return True # leave URL in field unchanged is applied to all URL fields in the :py:obj:`Plugin.on_result` hook: .. code:: python class MyUrlFilter(Plugin): ... def on_result(self, request, search, result) -> bool: result.filter_urls(my_url_filter) return True Implementation ============== .. autoclass:: Plugin :members: .. autoclass:: PluginInfo :members: .. autoclass:: PluginStorage :members: .. autoclass:: PluginCfg :members: """ __all__ = ["PluginInfo", "Plugin", "PluginStorage", "PluginCfg"] import searx from ._core import PluginInfo, Plugin, PluginStorage, PluginCfg STORAGE: PluginStorage = PluginStorage() def initialize(app): STORAGE.load_settings(searx.get_setting("plugins")) STORAGE.init(app)