mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-04-26 19:05:17 +00:00
4e5addd5df
- Updated `.gitignore` to include local configuration and plugin directories, allowing users to add custom commands and services without modifying core code. - Enhanced `config.ini.example` with instructions for using local plugins and added sections for local service configurations. - Refactored `PluginLoader` and `ServicePluginLoader` to support loading local commands and services from specified directories, improving extensibility. - Updated `mkdocs.yml` to include documentation for local plugins and the check-in API. - Added tests to verify the discovery and loading of local plugins, ensuring functionality and preventing name collisions with built-in plugins.
93 lines
5.0 KiB
Markdown
93 lines
5.0 KiB
Markdown
# Local plugins and services
|
||
|
||
You can add your own **command plugins** and **service plugins** without modifying the bot’s code by placing them in the **`local/`** directory. Their configuration can live in **`local/config.ini`** so it stays separate from the main `config.ini`.
|
||
|
||
## Directories
|
||
|
||
| Path | Purpose |
|
||
|------|---------|
|
||
| **local/commands/** | One Python file per command plugin (subclass of `BaseCommand`). |
|
||
| **local/service_plugins/** | One Python file per service plugin (subclass of `BaseServicePlugin`). |
|
||
| **local/config.ini** | Optional. Merged with main config; use it for your plugins’ sections. |
|
||
|
||
Local plugins are **additive**: they are loaded after built-in (and alternative) plugins. If a local plugin or service has the same logical **name** as one already loaded, it is **skipped** and a warning is logged. There is no override-by-name for local code.
|
||
|
||
## Minimal command plugin
|
||
|
||
Create a file in **local/commands/** (e.g. `local/commands/hello_local.py`):
|
||
|
||
```python
|
||
# local/commands/hello_local.py
|
||
from modules.commands.base_command import BaseCommand
|
||
from modules.models import MeshMessage
|
||
|
||
|
||
class HelloLocalCommand(BaseCommand):
|
||
name = "hellolocal"
|
||
keywords = ["hellolocal", "hi local"]
|
||
description = "A local greeting command"
|
||
|
||
async def execute(self, message: MeshMessage) -> bool:
|
||
return await self.handle_keyword_match(message)
|
||
```
|
||
|
||
- The bot discovers all `.py` files in `local/commands/` (except `__init__.py`).
|
||
- Each file must define exactly one class that inherits from `BaseCommand` and is not the base class itself.
|
||
- Use `bot.config` for options; you can put your section in **local/config.ini** (e.g. `[HelloLocal_Command]`) and read with `self.get_config_value('HelloLocal_Command', 'enabled', fallback=True, value_type='bool')` or `self.bot.config.get(...)`.
|
||
|
||
Restart the bot (or ensure the directory exists and the file is in place before starting). The command will be registered like any other.
|
||
|
||
## Minimal service plugin
|
||
|
||
Create a file in **local/service_plugins/** (e.g. `local/service_plugins/my_background_service.py`):
|
||
|
||
```python
|
||
# local/service_plugins/my_background_service.py
|
||
from modules.service_plugins.base_service import BaseServicePlugin
|
||
|
||
|
||
class MyBackgroundService(BaseServicePlugin):
|
||
config_section = "MyBackground"
|
||
description = "A local background service"
|
||
|
||
async def start(self) -> None:
|
||
self._running = True
|
||
self.logger.info("MyBackground service started")
|
||
|
||
async def stop(self) -> None:
|
||
self._running = False
|
||
self.logger.info("MyBackground service stopped")
|
||
```
|
||
|
||
- The bot discovers all `.py` files in `local/service_plugins/` (excluding `__init__.py`, `base_service.py`, and `*_utils.py`).
|
||
- The class must inherit from `BaseServicePlugin` and implement `start()` and `stop()`.
|
||
- To enable it, add a section in **local/config.ini** (or main config) with `enabled = true`:
|
||
|
||
```ini
|
||
[MyBackground]
|
||
enabled = true
|
||
```
|
||
|
||
Restart the bot so the service is loaded and started.
|
||
|
||
## Configuration
|
||
|
||
- **Main config** is read first, then **local/config.ini** if it exists. So `bot.config` contains both; later file wins on overlapping sections/keys.
|
||
- Put options for your local plugins in **local/config.ini** to keep main `config.ini` clean. Use the same section naming as built-in plugins (e.g. `[MyCommand_Command]` for a command, or a `config_section` for a service).
|
||
- After a **config reload** (e.g. via the `reload` command), both main config and `local/config.ini` are re-read, so on-demand config in your plugins will see updates. Plugin/service instances are not reloaded; only config values.
|
||
|
||
## Duplicate names
|
||
|
||
If a local command or service has the same **name** as an already-loaded plugin or service (e.g. you add `local/commands/ping.py` with `name = "ping"`), the local one is **skipped** and a warning is logged. Choose a different name (e.g. `pinglocal`) to avoid the conflict.
|
||
|
||
## References
|
||
|
||
- [Service plugins](service-plugins.md) — built-in services and how they are enabled.
|
||
- [Check-in API](checkin-api.md) — contract for the optional check-in submission API (local check-in service).
|
||
- Built-in command plugins live in **modules/commands/** and **modules/commands/alternatives/**; you can use them as examples for `BaseCommand`, `get_config_value`, `handle_keyword_match`, etc.
|
||
- Base classes: **modules/commands/base_command.py** (`BaseCommand`), **modules/service_plugins/base_service.py** (`BaseServicePlugin`).
|
||
|
||
## Check-in service (local)
|
||
|
||
The repo includes a local service plugin **`local/service_plugins/checkin_service.py`** that collects check-ins from a channel (default `#meshmonday`) on a chosen day (Monday only or daily). You can require a specific phrase (e.g. "check in") or count any message. Optionally it submits check-in data (packet hash, username, message) to a web API secured with an API key. Configuration belongs in **local/config.ini** under `[CheckIn]`. See **config.ini.example** for a commented `[CheckIn]` block and **[Check-in API](checkin-api.md)** for the API contract if you run or build a server to receive submissions.
|