Add Arrtrix runtime, config, onboarding, and webhook support

- Implement runtime package for bridge startup, config loading, and env
  overrides
- Add onboarding package for management room welcome messages
- Add matrixcmd package for command processing and help
- Add webhook package with Radarr webhook support and validation
- Extend connector config for webhooks and validation
- Update default config and example config for new options
- Add tests for new packages and config validation
- Change database type default to sqlite3-fk-wal
This commit is contained in:
Chris Kruining 2026-04-16 09:06:57 +02:00
parent eeedb5268a
commit fe627f3aab
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
19 changed files with 1855 additions and 35 deletions

View file

@ -0,0 +1,61 @@
package config
import (
"go.mau.fi/util/dbutil"
"go.mau.fi/zeroconfig"
"gopkg.in/yaml.v3"
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
)
type Config struct {
Network yaml.Node `yaml:"network"`
Bridge bridgeconfig.BridgeConfig `yaml:"bridge"`
Database dbutil.Config `yaml:"database"`
Homeserver bridgeconfig.HomeserverConfig `yaml:"homeserver"`
AppService bridgeconfig.AppserviceConfig `yaml:"appservice"`
Logging zeroconfig.Config `yaml:"logging"`
EnvConfigPrefix string `yaml:"env_config_prefix"`
ManagementTexts bridgeconfig.ManagementRoomTexts `yaml:"management_room_texts"`
}
func Load(data []byte) (*Config, error) {
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, err
}
cfg.applyDefaults()
return &cfg, nil
}
func (c *Config) applyDefaults() {
if c.Homeserver.Software == "" {
c.Homeserver.Software = bridgeconfig.SoftwareStandard
}
}
func (c *Config) Compile() bridgeconfig.Config {
return bridgeconfig.Config{
Network: c.Network,
Bridge: c.Bridge,
Database: c.Database,
Homeserver: c.Homeserver,
AppService: c.AppService,
Logging: c.Logging,
EnvConfigPrefix: c.EnvConfigPrefix,
ManagementRoomTexts: c.ManagementTexts,
Matrix: bridgeconfig.MatrixConfig{
MessageStatusEvents: false,
DeliveryReceipts: false,
MessageErrorNotices: true,
SyncDirectChatList: false,
FederateRooms: true,
},
DoublePuppet: bridgeconfig.DoublePuppetConfig{
Servers: map[string]string{},
Secrets: map[string]string{},
},
}
}

View file

@ -0,0 +1,122 @@
package config
import (
"testing"
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
)
func TestLoadDefaultsHomeserverSoftware(t *testing.T) {
cfg, err := Load([]byte(`
bridge:
command_prefix: "!arr"
homeserver:
address: http://127.0.0.1:8008
domain: test.local
appservice:
id: arrtrix
bot:
username: arrtrixbot
displayname: Arrtrix Bot
username_template: arrtrix_{{.}}
database:
type: sqlite3-fk-wal
uri: file:arrtrix.db?_txlock=immediate
logging:
min_level: info
writers:
- type: stdout
format: pretty-colored
`))
if err != nil {
t.Fatalf("Load returned error: %v", err)
}
if cfg.Homeserver.Software != bridgeconfig.SoftwareStandard {
t.Fatalf("expected homeserver software default %q, got %q", bridgeconfig.SoftwareStandard, cfg.Homeserver.Software)
}
}
func TestCompileSetsInternalDefaultsForHiddenSections(t *testing.T) {
cfg, err := Load([]byte(`
bridge:
command_prefix: "!arr"
permissions:
"*": relay
homeserver:
address: http://127.0.0.1:8008
domain: test.local
appservice:
id: arrtrix
bot:
username: arrtrixbot
displayname: Arrtrix Bot
username_template: arrtrix_{{.}}
database:
type: sqlite3-fk-wal
uri: file:arrtrix.db?_txlock=immediate
logging:
min_level: info
writers:
- type: stdout
format: pretty-colored
`))
if err != nil {
t.Fatalf("Load returned error: %v", err)
}
runtimeCfg := cfg.Compile()
if !runtimeCfg.Matrix.MessageErrorNotices {
t.Fatalf("expected message error notices to stay enabled")
}
if !runtimeCfg.Matrix.FederateRooms {
t.Fatalf("expected federated rooms to stay enabled")
}
if runtimeCfg.DoublePuppet.Servers == nil || runtimeCfg.DoublePuppet.Secrets == nil {
t.Fatalf("expected hidden double puppet maps to be initialized")
}
}
func TestLoadIgnoresLegacyHiddenSections(t *testing.T) {
cfg, err := Load([]byte(`
bridge:
command_prefix: "!arr"
homeserver:
address: http://127.0.0.1:8008
domain: test.local
appservice:
id: arrtrix
bot:
username: arrtrixbot
displayname: Arrtrix Bot
username_template: arrtrix_{{.}}
database:
type: sqlite3-fk-wal
uri: file:arrtrix.db?_txlock=immediate
logging:
min_level: info
writers:
- type: stdout
format: pretty-colored
matrix:
federate_rooms: false
provisioning:
shared_secret: ignored
double_puppet:
secrets:
test.local: secret
encryption:
allow: true
`))
if err != nil {
t.Fatalf("Load returned error: %v", err)
}
runtimeCfg := cfg.Compile()
if !runtimeCfg.Matrix.FederateRooms {
t.Fatalf("expected runtime defaults to win for hidden legacy sections")
}
if len(runtimeCfg.DoublePuppet.Secrets) != 0 {
t.Fatalf("expected hidden double puppet secrets to stay internal-only")
}
}