Getting Started with Module Development
This guide walks you through creating an ErisPulse module from scratch.
Project Structure
A standard module structure:
MyModule/
├── pyproject.toml
├── README.md
├── LICENSE
└── MyModule/
├── __init__.py
└── Core.py
pyproject.toml Configuration
[project]
name = "ErisPulse-MyModule"
version = "1.0.0"
description = "Module function description"
readme = "README.md"
requires-python = ">=3.10"
license = { file = "LICENSE" }
authors = [ { name = "yourname", email = "[email protected]" } ]
dependencies = []
[project.urls]
"homepage" = "https://github.com/yourname/MyModule"
[project.entry-points."erispulse.module"]
"MyModule" = "MyModule:Main"
init.py
from .Core import Main
Core.py - Core Module
from ErisPulse import sdk
from ErisPulse.Core.Bases import BaseModule
from ErisPulse.Core.Event import command
class Main(BaseModule):
def __init__(self, sdk):
self.sdk = sdk
self.logger = sdk.logger.get_child("MyModule")
self.storage = sdk.storage
@staticmethod
def get_load_strategy():
"""Returns the module loading strategy"""
from ErisPulse.loaders import ModuleLoadStrategy
return ModuleLoadStrategy(
lazy_load=True,
priority=0,
depends=[], # Optional: List of other modules this module depends on
# Optional: Event-driven lazy activation — declare triggers, module loads automatically when the first matching event/command arrives
# activate_on=[{"command": {"name": "hello", "help": "Send a greeting"}}],
)
async def on_load(self, event):
"""Called when the module is loaded"""
@command("hello", help="Send a greeting")
async def hello_command(event):
name = event.get_user_nickname() or "friend"
await event.reply(f"Hello, {name}!")
self.logger.info("Module loaded")
async def on_unload(self, event):
"""Called when the module is unloaded"""
self.logger.info("Module unloaded")
Configuration Reading: The basic example above does not use configuration. When configuration reading is needed, it is recommended to declare a nested
ConfigClassand read it in real time viaself.cfg(see Core Module Concepts). The old method of manually calling_load_config()has been deprecated.
Testing Module
Local Testing
# Install the module in the project directory
epsdk install ./MyModule
# Run the project
epsdk run main.py --reload
Test Commands
Send a command to test:
/hello
Core Concepts
BaseModule Base Class
All modules must inherit from BaseModule, providing the following methods:
| Method | Description | Required |
|---|---|---|
__init__(self, sdk) |
Constructor (framework passes sdk instance) |
No |
get_load_strategy() |
Returns the load strategy | No |
get_meta() |
Returns module metadata (optional) | No |
on_load(self, event) |
Called when the module is loaded | Yes |
on_unload(self, event) |
Called when the module is unloaded | Yes |
Module Meta Information
Note
This feature requires ErisPulse 2.8.0+.
Declare module metadata (what the module does, its category, etc.) via get_meta().
Metadata is the general introduction data of a module, consumed by help modules, dashboard module lists, module stores, and other interfaces/ecosystem modules.
Similar to get_load_strategy() returning ModuleLoadStrategy, it is recommended to return an instance of the ModuleMeta configuration class (with type hints and IDE completion), but direct return of a dict is also supported:
class MyModule(BaseModule):
@staticmethod
def get_meta() -> ModuleMeta:
return ModuleMeta(
name="Weather", # Display name (default registration name)
description="Query city weather", # Module description
version="1.0.0",
author="ErisDev",
group="Tools", # Function group
tags=["Weather", "Query"],
)
Alternative dict-based approach:
class MyModule(BaseModule):
@staticmethod
def get_meta() -> dict:
return {
"name": "Weather",
"description": "Query city weather",
"version": "1.0.0",
"author": "ErisDev",
"group": "Tools",
"tags": ["Weather", "Query"],
}
module.get_meta("MyModule")retrieves the parsed metadata (class declaration > registered info, automatically completing the module's command name).module.get_commands_overview()aggregates "module meta + its registered commands (aliases/groups/help)" into a module-organized command overview.- The module owner of a command can be obtained via
cmd_info["owner"](automatically injected by the context system during registration).
i18n Support for Meta Fields
The values of meta information fields can be plain strings or i18n dictionaries {"i18n": "key.path", "default": "fallback text"} (consistent with the description configuration convention).
Translation keys are declared and registered via I18nClass. When reading with module.get_meta(), the values are automatically resolved into the current language text:
class MyModule(BaseModule):
class I18nClass(BaseI18n):
meta_description: I18nKey = I18nKey(
default="Weather lookup",
zh_CN="查询城市天气",
en="Weather lookup",
)
@staticmethod
def get_meta() -> ModuleMeta:
return ModuleMeta(
name="Weather",
description={"i18n": "MyModule.meta_description", "default": "Weather lookup"},
)
SDK Object
Access core features through the sdk object:
from ErisPulse import sdk
sdk.storage # Storage system
sdk.config # Configuration system
sdk.logger # Logging system
sdk.adapter # Adapter system
sdk.router # Routing system
sdk.lifecycle # Lifecycle system
Next Steps
- Core Concepts of Modules - Dive deeper into the module architecture
- Event Wrapper Class Details - Learn about the Event object
- Best Practices for Modules - Develop high-quality modules