The plugin event bus provides publish/subscribe communication between plugins.
PluginEventBus is an in-process pub/sub system. Plugins can subscribe to topics and publish events. Each handler invocation is wrapped in panic recovery.
type PluginEventBus struct { ... }
func NewPluginEventBus() *PluginEventBus
func (b *PluginEventBus) Subscribe(topic string, handler PluginEventHandler) error
func (b *PluginEventBus) Publish(ctx context.Context, topic string, data any) []error
func (b *PluginEventBus) Unsubscribe(topic string, handler PluginEventHandler) error
Handler signature:
type PluginEventHandler func(ctx context.Context, topic string, data any) error
| Action | Required Permission |
|---|---|
| Subscribe | bus.read |
| Publish | bus.write |
| Both (plugin-to-plugin) | bus.plugin (implies bus.read + bus.write) |
func (p *MyPlugin) Activate(ctx plugin.PluginContext) error {
return ctx.Subscribe("xbot.my-plugin:events", func(ctx context.Context, topic string, data any) error {
logger := ctx.Logger()
logger.Info("Received event", plugin.Field{Key: "topic", Value: topic})
return nil
})
}
func (p *MyPlugin) DoSomething(ctx plugin.PluginContext) error {
return ctx.Publish("xbot.my-plugin:events", map[string]any{
"action": "completed",
"timestamp": time.Now().Unix(),
})
}
// Unsubscribe uses function pointer comparison
handler := func(ctx context.Context, topic string, data any) error { return nil }
ctx.Subscribe("topic", handler)
// Later:
ctx.Unsubscribe("topic", handler) // Must be the same function reference
Use reverse-DNS style with plugin ID prefix:
xbot.<plugin-id>:<event-name>
Examples:
xbot.git-fancy:commit— Git Fancy plugin commit eventxbot.my-plugin:ready— My plugin ready event
- Thread-safe: Protected by
sync.RWMutex - Copy-on-read: Handlers are copied before iteration, so subscribe/unsubscribe during publish is safe
- Panic recovery: Each handler is wrapped in
recover(). Panics are returned as errors, not propagated - Unsubscribe: Uses function pointer comparison (
reflect.ValueOf().Pointer())
- PluginContext API — EventBusPublisher interface
- Permissions —
bus.read,bus.write,bus.plugin