mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 20:01:17 +00:00
[core] Add channel specific module configuration interface
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
dc648d1dba
commit
0a53863b69
6 changed files with 100 additions and 4 deletions
|
@ -56,6 +56,7 @@ type (
|
||||||
PermitAllowModerator bool `yaml:"permit_allow_moderator"`
|
PermitAllowModerator bool `yaml:"permit_allow_moderator"`
|
||||||
PermitTimeout time.Duration `yaml:"permit_timeout"`
|
PermitTimeout time.Duration `yaml:"permit_timeout"`
|
||||||
RawLog string `yaml:"raw_log"`
|
RawLog string `yaml:"raw_log"`
|
||||||
|
ModuleConfig plugins.ModuleConfig `yaml:"module_config"`
|
||||||
Rules []*plugins.Rule `yaml:"rules"`
|
Rules []*plugins.Rule `yaml:"rules"`
|
||||||
Variables map[string]interface{} `yaml:"variables"`
|
Variables map[string]interface{} `yaml:"variables"`
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,17 @@ auto_messages:
|
||||||
# Disable message using templating, must yield string `true` to disable the automated message
|
# Disable message using templating, must yield string `true` to disable the automated message
|
||||||
disable_on_template: '{{ ne .myvariable true }}'
|
disable_on_template: '{{ ne .myvariable true }}'
|
||||||
|
|
||||||
|
# Module configuration by channel or defining bot-wide defaults. See
|
||||||
|
# module specific documentation for options to configure in this
|
||||||
|
# section. All modules come with internal defaults so there is no
|
||||||
|
# need to configure this but you can overwrite the internal defaults.
|
||||||
|
module_config:
|
||||||
|
some-module: # Name of the module to configure
|
||||||
|
default: # Bot-wide, fallback for all channels
|
||||||
|
some_option: true
|
||||||
|
mychannel: # Channel-specific, only valid for this channel
|
||||||
|
some_option: false
|
||||||
|
|
||||||
# List of rules. See documentation for details or use web-interface
|
# List of rules. See documentation for details or use web-interface
|
||||||
# to configure.
|
# to configure.
|
||||||
rules: # See below for examples
|
rules: # See below for examples
|
||||||
|
|
|
@ -43,6 +43,8 @@ type (
|
||||||
|
|
||||||
LoggerCreationFunc func(moduleName string) *log.Entry
|
LoggerCreationFunc func(moduleName string) *log.Entry
|
||||||
|
|
||||||
|
ModuleConfigGetterFunc func(module, channel string) *FieldCollection
|
||||||
|
|
||||||
MsgFormatter func(tplString string, m *irc.Message, r *Rule, fields *FieldCollection) (string, error)
|
MsgFormatter func(tplString string, m *irc.Message, r *Rule, fields *FieldCollection) (string, error)
|
||||||
|
|
||||||
MsgModificationFunc func(*irc.Message) error
|
MsgModificationFunc func(*irc.Message) error
|
||||||
|
@ -65,6 +67,8 @@ type (
|
||||||
GetDatabaseConnector func() database.Connector
|
GetDatabaseConnector func() database.Connector
|
||||||
// GetLogger returns a sirupsen log.Entry pre-configured with the module name
|
// GetLogger returns a sirupsen log.Entry pre-configured with the module name
|
||||||
GetLogger LoggerCreationFunc
|
GetLogger LoggerCreationFunc
|
||||||
|
// GetModuleConfigForChannel returns the module configuration for the given channel if available
|
||||||
|
GetModuleConfigForChannel ModuleConfigGetterFunc
|
||||||
// GetTwitchClient retrieves a fully configured Twitch client with initialized cache
|
// GetTwitchClient retrieves a fully configured Twitch client with initialized cache
|
||||||
GetTwitchClient func() *twitch.Client
|
GetTwitchClient func() *twitch.Client
|
||||||
// GetTwitchClientForChannel retrieves a fully configured Twitch client with initialized cache for extended permission channels
|
// GetTwitchClientForChannel retrieves a fully configured Twitch client with initialized cache for extended permission channels
|
||||||
|
|
37
plugins/moduleConfig.go
Normal file
37
plugins/moduleConfig.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package plugins
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// DefaultConfigName is the name the default configuration must have
|
||||||
|
// when defined
|
||||||
|
const DefaultConfigName = "default"
|
||||||
|
|
||||||
|
type (
|
||||||
|
// ModuleConfig represents a mapping of configurations per channel
|
||||||
|
// and module
|
||||||
|
ModuleConfig map[string]map[string]*FieldCollection
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetChannelConfig reads the channel specific configuration for the
|
||||||
|
// given module. This is created by taking an empty FieldCollection,
|
||||||
|
// merging in the default configuration and finally overwriting all
|
||||||
|
// existing channel configurations.
|
||||||
|
func (m ModuleConfig) GetChannelConfig(module, channel string) *FieldCollection {
|
||||||
|
channel = strings.TrimLeft(channel, "#@")
|
||||||
|
composed := NewFieldCollection()
|
||||||
|
|
||||||
|
for _, i := range []string{DefaultConfigName, channel} {
|
||||||
|
f := m[module][i]
|
||||||
|
if f == nil {
|
||||||
|
// That config does not exist, don't apply
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range f.Data() {
|
||||||
|
// Overwrite all keys defined in this config
|
||||||
|
composed.Set(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return composed
|
||||||
|
}
|
38
plugins/moduleConfig_test.go
Normal file
38
plugins/moduleConfig_test.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package plugins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestModuleConfigGet(t *testing.T) {
|
||||||
|
strPtrEmpty := func(v string) *string { return &v }("")
|
||||||
|
m := ModuleConfig{
|
||||||
|
"test": map[string]*FieldCollection{
|
||||||
|
DefaultConfigName: FieldCollectionFromData(map[string]any{
|
||||||
|
"setindefault": DefaultConfigName,
|
||||||
|
"setinboth": DefaultConfigName,
|
||||||
|
}),
|
||||||
|
"test": FieldCollectionFromData(map[string]any{
|
||||||
|
"setinchannel": "channel",
|
||||||
|
"setinboth": "channel",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := m.GetChannelConfig("module_does_not_exist", "test")
|
||||||
|
require.NotNil(t, fields, "must always return a valid FieldCollection")
|
||||||
|
assert.Len(t, fields.Data(), 0)
|
||||||
|
|
||||||
|
fields = m.GetChannelConfig("test", "test")
|
||||||
|
assert.Equal(t, DefaultConfigName, fields.MustString("setindefault", strPtrEmpty))
|
||||||
|
assert.Equal(t, "channel", fields.MustString("setinchannel", strPtrEmpty))
|
||||||
|
assert.Equal(t, "channel", fields.MustString("setinboth", strPtrEmpty))
|
||||||
|
|
||||||
|
fields = m.GetChannelConfig("test", "channel_not_configured")
|
||||||
|
assert.Equal(t, DefaultConfigName, fields.MustString("setindefault", strPtrEmpty))
|
||||||
|
assert.Equal(t, "", fields.MustString("setinchannel", strPtrEmpty))
|
||||||
|
assert.Equal(t, DefaultConfigName, fields.MustString("setinboth", strPtrEmpty))
|
||||||
|
}
|
|
@ -148,10 +148,6 @@ func registerRoute(route plugins.HTTPRouteRegistrationArgs) error {
|
||||||
|
|
||||||
func getRegistrationArguments() plugins.RegistrationArguments {
|
func getRegistrationArguments() plugins.RegistrationArguments {
|
||||||
return plugins.RegistrationArguments{
|
return plugins.RegistrationArguments{
|
||||||
CreateEvent: func(evt string, eventData *plugins.FieldCollection) error {
|
|
||||||
handleMessage(ircHdl.Client(), nil, &evt, eventData)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
FormatMessage: formatMessage,
|
FormatMessage: formatMessage,
|
||||||
FrontendNotify: func(mt string) { frontendNotifyHooks.Ping(mt) },
|
FrontendNotify: func(mt string) { frontendNotifyHooks.Ping(mt) },
|
||||||
GetDatabaseConnector: func() database.Connector { return db },
|
GetDatabaseConnector: func() database.Connector { return db },
|
||||||
|
@ -170,6 +166,15 @@ func getRegistrationArguments() plugins.RegistrationArguments {
|
||||||
SendMessage: sendMessage,
|
SendMessage: sendMessage,
|
||||||
ValidateToken: validateAuthToken,
|
ValidateToken: validateAuthToken,
|
||||||
|
|
||||||
|
CreateEvent: func(evt string, eventData *plugins.FieldCollection) error {
|
||||||
|
handleMessage(ircHdl.Client(), nil, &evt, eventData)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
|
||||||
|
GetModuleConfigForChannel: func(module, channel string) *plugins.FieldCollection {
|
||||||
|
return config.ModuleConfig.GetChannelConfig(module, channel)
|
||||||
|
},
|
||||||
|
|
||||||
GetTwitchClientForChannel: func(channel string) (*twitch.Client, error) {
|
GetTwitchClientForChannel: func(channel string) (*twitch.Client, error) {
|
||||||
return accessService.GetTwitchClientForChannel(channel, access.ClientConfig{
|
return accessService.GetTwitchClientForChannel(channel, access.ClientConfig{
|
||||||
TwitchClient: cfg.TwitchClient,
|
TwitchClient: cfg.TwitchClient,
|
||||||
|
|
Loading…
Reference in a new issue