feat: add hot-reload, shorthand commands, and plugin help

- Plugin registry: add unload_plugin(), reload_plugin(), path tracking
- Bot: add load_plugin(), reload_plugin(), unload_plugin() public API
- Core plugin: add !load, !reload, !unload, !plugins commands
- Command dispatch: support unambiguous prefix matching (!h -> !help)
- Help: support !help <plugin> to show plugin description and commands
- Tests: 17 new tests covering hot-reload, prefix matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-15 01:15:59 +01:00
parent ad18a902dd
commit 77f9a364e6
6 changed files with 508 additions and 22 deletions

View File

@@ -49,9 +49,26 @@ level = "info" # Logging level: debug, info, warning, error
| `!ping` | Bot responds with "pong" |
| `!help` | List all available commands |
| `!help <cmd>` | Show help for a specific command |
| `!help <plugin>` | Show plugin description and its commands |
| `!version` | Show bot version |
| `!echo <text>` | Echo back text (example plugin) |
| `!cert <domain> [...]` | Lookup CT logs for up to 5 domains |
| `!load <plugin>` | Hot-load a plugin from the plugins directory |
| `!reload <plugin>` | Reload a plugin, picking up file changes |
| `!unload <plugin>` | Unload a plugin, removing its handlers |
| `!plugins` | List loaded plugins with handler counts |
### Command Shorthand
Commands can be abbreviated to any unambiguous prefix:
```
!h -> !help (unique match)
!pi -> !ping (unique match)
!p -> error: ambiguous (ping, plugins)
```
Exact matches always take priority over prefix matches.
### `!cert` -- Certificate Transparency Lookup
@@ -76,6 +93,21 @@ broken.test -- error: timeout
- crt.sh can be slow; the bot confirms receipt before querying
- Live cert check runs only when expired CT entries exist
## Plugin Management
Plugins can be loaded, unloaded, and reloaded at runtime without
restarting the bot.
```
!load crtsh # Hot-load a new plugin from plugins/
!reload crtsh # Reload a changed plugin
!unload crtsh # Remove a plugin and all its handlers
!plugins # List loaded plugins with handler counts
```
The `core` plugin cannot be unloaded (prevents losing `!load`/`!reload`),
but it can be reloaded.
## Writing Plugins
Create a `.py` file in the `plugins/` directory: