Move config upgrade helper to mautrix-go

This commit is contained in:
Tulir Asokan 2022-05-21 12:06:07 +03:00
parent f1a4cfe7d5
commit 42a4839a4e
3 changed files with 153 additions and 481 deletions

View file

@ -17,214 +17,163 @@
package config
import (
"fmt"
"os"
"path"
"strings"
"gopkg.in/yaml.v3"
"maunium.net/go/mautrix/appservice"
up "maunium.net/go/mautrix/util/configupgrade"
)
func (helper *UpgradeHelper) doUpgrade() {
helper.Copy(Str, "homeserver", "address")
helper.Copy(Str, "homeserver", "domain")
helper.Copy(Bool, "homeserver", "asmux")
helper.Copy(Str|Null, "homeserver", "status_endpoint")
helper.Copy(Str|Null, "homeserver", "message_send_checkpoint_endpoint")
helper.Copy(Bool, "homeserver", "async_media")
type waUpgrader struct{}
helper.Copy(Str, "appservice", "address")
helper.Copy(Str, "appservice", "hostname")
helper.Copy(Int, "appservice", "port")
helper.Copy(Str, "appservice", "database", "type")
helper.Copy(Str, "appservice", "database", "uri")
helper.Copy(Int, "appservice", "database", "max_open_conns")
helper.Copy(Int, "appservice", "database", "max_idle_conns")
helper.Copy(Str|Null, "appservice", "database", "max_conn_idle_time")
helper.Copy(Str|Null, "appservice", "database", "max_conn_lifetime")
if prefix, ok := helper.Get(Str, "appservice", "provisioning", "prefix"); ok && strings.HasSuffix(prefix, "/v1") {
helper.Set(Str, strings.TrimSuffix(prefix, "/v1"), "appservice", "provisioning", "prefix")
} else {
helper.Copy(Str, "appservice", "provisioning", "prefix")
}
if secret, ok := helper.Get(Str, "appservice", "provisioning", "shared_secret"); !ok || secret == "generate" {
sharedSecret := appservice.RandomString(64)
helper.Set(Str, sharedSecret, "appservice", "provisioning", "shared_secret")
} else {
helper.Copy(Str, "appservice", "provisioning", "shared_secret")
}
helper.Copy(Str, "appservice", "id")
helper.Copy(Str, "appservice", "bot", "username")
helper.Copy(Str, "appservice", "bot", "displayname")
helper.Copy(Str, "appservice", "bot", "avatar")
helper.Copy(Bool, "appservice", "ephemeral_events")
helper.Copy(Str, "appservice", "as_token")
helper.Copy(Str, "appservice", "hs_token")
helper.Copy(Str|Null, "segment_key")
helper.Copy(Bool, "metrics", "enabled")
helper.Copy(Str, "metrics", "listen")
helper.Copy(Str, "whatsapp", "os_name")
helper.Copy(Str, "whatsapp", "browser_name")
helper.Copy(Str, "bridge", "username_template")
helper.Copy(Str, "bridge", "displayname_template")
helper.Copy(Bool, "bridge", "personal_filtering_spaces")
helper.Copy(Bool, "bridge", "delivery_receipts")
helper.Copy(Int, "bridge", "portal_message_buffer")
helper.Copy(Bool, "bridge", "call_start_notices")
helper.Copy(Bool, "bridge", "identity_change_notices")
helper.Copy(Bool, "bridge", "history_sync", "create_portals")
helper.Copy(Bool, "bridge", "history_sync", "backfill")
helper.Copy(Bool, "bridge", "history_sync", "double_puppet_backfill")
helper.Copy(Bool, "bridge", "history_sync", "request_full_sync")
helper.Copy(Bool, "bridge", "history_sync", "media_requests", "auto_request_media")
helper.Copy(Str, "bridge", "history_sync", "media_requests", "request_method")
helper.Copy(Int, "bridge", "history_sync", "media_requests", "request_local_time")
helper.Copy(Int, "bridge", "history_sync", "max_initial_conversations")
helper.Copy(Int, "bridge", "history_sync", "immediate", "worker_count")
helper.Copy(Int, "bridge", "history_sync", "immediate", "max_events")
helper.Copy(List, "bridge", "history_sync", "deferred")
helper.Copy(Bool, "bridge", "user_avatar_sync")
helper.Copy(Bool, "bridge", "bridge_matrix_leave")
helper.Copy(Bool, "bridge", "sync_with_custom_puppets")
helper.Copy(Bool, "bridge", "sync_direct_chat_list")
helper.Copy(Bool, "bridge", "default_bridge_receipts")
helper.Copy(Bool, "bridge", "default_bridge_presence")
helper.Copy(Bool, "bridge", "send_presence_on_typing")
helper.Copy(Bool, "bridge", "force_active_delivery_receipts")
helper.Copy(Map, "bridge", "double_puppet_server_map")
helper.Copy(Bool, "bridge", "double_puppet_allow_discovery")
if legacySecret, ok := helper.Get(Str, "bridge", "login_shared_secret"); ok && len(legacySecret) > 0 {
baseNode := helper.GetBaseNode("bridge", "login_shared_secret_map")
baseNode.Map[helper.GetBase("homeserver", "domain")] = YAMLNode{Node: makeStringNode(legacySecret)}
baseNode.Content = baseNode.Map.toNodes()
} else {
helper.Copy(Map, "bridge", "login_shared_secret_map")
}
helper.Copy(Bool, "bridge", "private_chat_portal_meta")
helper.Copy(Bool, "bridge", "bridge_notices")
helper.Copy(Bool, "bridge", "resend_bridge_info")
helper.Copy(Bool, "bridge", "mute_bridging")
helper.Copy(Str|Null, "bridge", "archive_tag")
helper.Copy(Str|Null, "bridge", "pinned_tag")
helper.Copy(Bool, "bridge", "tag_only_on_create")
helper.Copy(Bool, "bridge", "enable_status_broadcast")
helper.Copy(Bool, "bridge", "mute_status_broadcast")
helper.Copy(Str|Null, "bridge", "status_broadcast_tag")
helper.Copy(Bool, "bridge", "whatsapp_thumbnail")
helper.Copy(Bool, "bridge", "allow_user_invite")
helper.Copy(Str, "bridge", "command_prefix")
helper.Copy(Bool, "bridge", "federate_rooms")
helper.Copy(Bool, "bridge", "disappearing_messages_in_groups")
helper.Copy(Bool, "bridge", "disable_bridge_alerts")
helper.Copy(Bool, "bridge", "url_previews")
helper.Copy(Str, "bridge", "management_room_text", "welcome")
helper.Copy(Str, "bridge", "management_room_text", "welcome_connected")
helper.Copy(Str, "bridge", "management_room_text", "welcome_unconnected")
helper.Copy(Str|Null, "bridge", "management_room_text", "additional_help")
helper.Copy(Bool, "bridge", "encryption", "allow")
helper.Copy(Bool, "bridge", "encryption", "default")
helper.Copy(Bool, "bridge", "encryption", "key_sharing", "allow")
helper.Copy(Bool, "bridge", "encryption", "key_sharing", "require_cross_signing")
helper.Copy(Bool, "bridge", "encryption", "key_sharing", "require_verification")
helper.Copy(Map, "bridge", "permissions")
helper.Copy(Bool, "bridge", "relay", "enabled")
helper.Copy(Bool, "bridge", "relay", "admin_only")
helper.Copy(Map, "bridge", "relay", "message_formats")
helper.Copy(Str, "logging", "directory")
helper.Copy(Str|Null, "logging", "file_name_format")
helper.Copy(Str|Timestamp, "logging", "file_date_format")
helper.Copy(Int, "logging", "file_mode")
helper.Copy(Str|Timestamp, "logging", "timestamp_format")
helper.Copy(Str, "logging", "print_level")
func (wau waUpgrader) GetBase() string {
return ExampleConfig
}
func Mutate(path string, mutate func(helper *UpgradeHelper)) error {
_, _, err := upgrade(path, true, mutate)
func (wau waUpgrader) DoUpgrade(helper *up.Helper) {
helper.Copy(up.Str, "homeserver", "address")
helper.Copy(up.Str, "homeserver", "domain")
helper.Copy(up.Bool, "homeserver", "asmux")
helper.Copy(up.Str|up.Null, "homeserver", "status_endpoint")
helper.Copy(up.Str|up.Null, "homeserver", "message_send_checkpoint_endpoint")
helper.Copy(up.Bool, "homeserver", "async_media")
helper.Copy(up.Str, "appservice", "address")
helper.Copy(up.Str, "appservice", "hostname")
helper.Copy(up.Int, "appservice", "port")
helper.Copy(up.Str, "appservice", "database", "type")
helper.Copy(up.Str, "appservice", "database", "uri")
helper.Copy(up.Int, "appservice", "database", "max_open_conns")
helper.Copy(up.Int, "appservice", "database", "max_idle_conns")
helper.Copy(up.Str|up.Null, "appservice", "database", "max_conn_idle_time")
helper.Copy(up.Str|up.Null, "appservice", "database", "max_conn_lifetime")
if prefix, ok := helper.Get(up.Str, "appservice", "provisioning", "prefix"); ok && strings.HasSuffix(prefix, "/v1") {
helper.Set(up.Str, strings.TrimSuffix(prefix, "/v1"), "appservice", "provisioning", "prefix")
} else {
helper.Copy(up.Str, "appservice", "provisioning", "prefix")
}
if secret, ok := helper.Get(up.Str, "appservice", "provisioning", "shared_secret"); !ok || secret == "generate" {
sharedSecret := appservice.RandomString(64)
helper.Set(up.Str, sharedSecret, "appservice", "provisioning", "shared_secret")
} else {
helper.Copy(up.Str, "appservice", "provisioning", "shared_secret")
}
helper.Copy(up.Str, "appservice", "id")
helper.Copy(up.Str, "appservice", "bot", "username")
helper.Copy(up.Str, "appservice", "bot", "displayname")
helper.Copy(up.Str, "appservice", "bot", "avatar")
helper.Copy(up.Bool, "appservice", "ephemeral_events")
helper.Copy(up.Str, "appservice", "as_token")
helper.Copy(up.Str, "appservice", "hs_token")
helper.Copy(up.Str|up.Null, "segment_key")
helper.Copy(up.Bool, "metrics", "enabled")
helper.Copy(up.Str, "metrics", "listen")
helper.Copy(up.Str, "whatsapp", "os_name")
helper.Copy(up.Str, "whatsapp", "browser_name")
helper.Copy(up.Str, "bridge", "username_template")
helper.Copy(up.Str, "bridge", "displayname_template")
helper.Copy(up.Bool, "bridge", "personal_filtering_spaces")
helper.Copy(up.Bool, "bridge", "delivery_receipts")
helper.Copy(up.Int, "bridge", "portal_message_buffer")
helper.Copy(up.Bool, "bridge", "call_start_notices")
helper.Copy(up.Bool, "bridge", "identity_change_notices")
helper.Copy(up.Bool, "bridge", "history_sync", "create_portals")
helper.Copy(up.Bool, "bridge", "history_sync", "backfill")
helper.Copy(up.Bool, "bridge", "history_sync", "double_puppet_backfill")
helper.Copy(up.Bool, "bridge", "history_sync", "request_full_sync")
helper.Copy(up.Bool, "bridge", "history_sync", "media_requests", "auto_request_media")
helper.Copy(up.Str, "bridge", "history_sync", "media_requests", "request_method")
helper.Copy(up.Int, "bridge", "history_sync", "media_requests", "request_local_time")
helper.Copy(up.Int, "bridge", "history_sync", "max_initial_conversations")
helper.Copy(up.Int, "bridge", "history_sync", "immediate", "worker_count")
helper.Copy(up.Int, "bridge", "history_sync", "immediate", "max_events")
helper.Copy(up.List, "bridge", "history_sync", "deferred")
helper.Copy(up.Bool, "bridge", "user_avatar_sync")
helper.Copy(up.Bool, "bridge", "bridge_matrix_leave")
helper.Copy(up.Bool, "bridge", "sync_with_custom_puppets")
helper.Copy(up.Bool, "bridge", "sync_direct_chat_list")
helper.Copy(up.Bool, "bridge", "default_bridge_receipts")
helper.Copy(up.Bool, "bridge", "default_bridge_presence")
helper.Copy(up.Bool, "bridge", "send_presence_on_typing")
helper.Copy(up.Bool, "bridge", "force_active_delivery_receipts")
helper.Copy(up.Map, "bridge", "double_puppet_server_map")
helper.Copy(up.Bool, "bridge", "double_puppet_allow_discovery")
if legacySecret, ok := helper.Get(up.Str, "bridge", "login_shared_secret"); ok && len(legacySecret) > 0 {
baseNode := helper.GetBaseNode("bridge", "login_shared_secret_map")
baseNode.Map[helper.GetBase("homeserver", "domain")] = up.StringNode(legacySecret)
baseNode.UpdateContent()
} else {
helper.Copy(up.Map, "bridge", "login_shared_secret_map")
}
helper.Copy(up.Bool, "bridge", "private_chat_portal_meta")
helper.Copy(up.Bool, "bridge", "bridge_notices")
helper.Copy(up.Bool, "bridge", "resend_bridge_info")
helper.Copy(up.Bool, "bridge", "mute_bridging")
helper.Copy(up.Str|up.Null, "bridge", "archive_tag")
helper.Copy(up.Str|up.Null, "bridge", "pinned_tag")
helper.Copy(up.Bool, "bridge", "tag_only_on_create")
helper.Copy(up.Bool, "bridge", "enable_status_broadcast")
helper.Copy(up.Bool, "bridge", "mute_status_broadcast")
helper.Copy(up.Str|up.Null, "bridge", "status_broadcast_tag")
helper.Copy(up.Bool, "bridge", "whatsapp_thumbnail")
helper.Copy(up.Bool, "bridge", "allow_user_invite")
helper.Copy(up.Str, "bridge", "command_prefix")
helper.Copy(up.Bool, "bridge", "federate_rooms")
helper.Copy(up.Bool, "bridge", "disappearing_messages_in_groups")
helper.Copy(up.Bool, "bridge", "disable_bridge_alerts")
helper.Copy(up.Bool, "bridge", "url_previews")
helper.Copy(up.Str, "bridge", "management_room_text", "welcome")
helper.Copy(up.Str, "bridge", "management_room_text", "welcome_connected")
helper.Copy(up.Str, "bridge", "management_room_text", "welcome_unconnected")
helper.Copy(up.Str|up.Null, "bridge", "management_room_text", "additional_help")
helper.Copy(up.Bool, "bridge", "encryption", "allow")
helper.Copy(up.Bool, "bridge", "encryption", "default")
helper.Copy(up.Bool, "bridge", "encryption", "key_sharing", "allow")
helper.Copy(up.Bool, "bridge", "encryption", "key_sharing", "require_cross_signing")
helper.Copy(up.Bool, "bridge", "encryption", "key_sharing", "require_verification")
helper.Copy(up.Map, "bridge", "permissions")
helper.Copy(up.Bool, "bridge", "relay", "enabled")
helper.Copy(up.Bool, "bridge", "relay", "admin_only")
helper.Copy(up.Map, "bridge", "relay", "message_formats")
helper.Copy(up.Str, "logging", "directory")
helper.Copy(up.Str|up.Null, "logging", "file_name_format")
helper.Copy(up.Str|up.Timestamp, "logging", "file_date_format")
helper.Copy(up.Int, "logging", "file_mode")
helper.Copy(up.Str|up.Timestamp, "logging", "timestamp_format")
helper.Copy(up.Str, "logging", "print_level")
}
func (wau waUpgrader) SpacedBlocks() [][]string {
return [][]string{
{"homeserver", "asmux"},
{"appservice"},
{"appservice", "hostname"},
{"appservice", "database"},
{"appservice", "provisioning"},
{"appservice", "id"},
{"appservice", "as_token"},
{"segment_key"},
{"metrics"},
{"whatsapp"},
{"bridge"},
{"bridge", "command_prefix"},
{"bridge", "management_room_text"},
{"bridge", "encryption"},
{"bridge", "permissions"},
{"bridge", "relay"},
{"logging"},
}
}
func Mutate(path string, mutate func(helper *up.Helper)) error {
_, _, err := up.Do(path, true, waUpgrader{}, up.SimpleUpgrader(mutate))
return err
}
func Upgrade(path string, save bool) ([]byte, bool, error) {
return upgrade(path, save, nil)
}
func (helper *UpgradeHelper) addSpaceBeforeComment(path ...string) {
node := helper.GetBaseNode(path...)
if node.Key == nil {
panic(fmt.Errorf("didn't find key at %+v", path))
}
node.Key.HeadComment = "\n" + node.Key.HeadComment
}
func (helper *UpgradeHelper) addSpaces() {
// The yaml package doesn't preserve blank lines, so re-add them manually where appropriate
helper.addSpaceBeforeComment("homeserver", "asmux")
helper.addSpaceBeforeComment("appservice")
helper.addSpaceBeforeComment("appservice", "hostname")
helper.addSpaceBeforeComment("appservice", "database")
helper.addSpaceBeforeComment("appservice", "provisioning")
helper.addSpaceBeforeComment("appservice", "id")
helper.addSpaceBeforeComment("appservice", "as_token")
helper.addSpaceBeforeComment("segment_key")
helper.addSpaceBeforeComment("metrics")
helper.addSpaceBeforeComment("whatsapp")
helper.addSpaceBeforeComment("bridge")
helper.addSpaceBeforeComment("bridge", "command_prefix")
helper.addSpaceBeforeComment("bridge", "management_room_text")
helper.addSpaceBeforeComment("bridge", "encryption")
helper.addSpaceBeforeComment("bridge", "permissions")
helper.addSpaceBeforeComment("bridge", "relay")
helper.addSpaceBeforeComment("logging")
}
func upgrade(configPath string, save bool, mutate func(helper *UpgradeHelper)) ([]byte, bool, error) {
sourceData, err := os.ReadFile(configPath)
if err != nil {
return nil, false, fmt.Errorf("failed to read config: %w", err)
}
var base, cfg yaml.Node
err = yaml.Unmarshal([]byte(ExampleConfig), &base)
if err != nil {
return sourceData, false, fmt.Errorf("failed to unmarshal example config: %w", err)
}
err = yaml.Unmarshal(sourceData, &cfg)
if err != nil {
return sourceData, false, fmt.Errorf("failed to unmarshal config: %w", err)
}
helper := NewUpgradeHelper(&base, &cfg)
helper.doUpgrade()
if mutate != nil {
mutate(helper)
}
helper.addSpaces()
output, err := yaml.Marshal(&base)
if err != nil {
return sourceData, false, fmt.Errorf("failed to marshal updated config: %w", err)
}
if save {
var tempFile *os.File
tempFile, err = os.CreateTemp(path.Dir(configPath), "wa-config-*.yaml")
if err != nil {
return output, true, fmt.Errorf("failed to create temp file for writing config: %w", err)
}
_, err = tempFile.Write(output)
if err != nil {
_ = os.Remove(tempFile.Name())
return output, true, fmt.Errorf("failed to write updated config to temp file: %w", err)
}
err = os.Rename(tempFile.Name(), configPath)
if err != nil {
_ = os.Remove(tempFile.Name())
return output, true, fmt.Errorf("failed to override current config with temp file: %w", err)
}
}
return output, true, nil
return up.Do(path, save, waUpgrader{})
}

View file

@ -1,278 +0,0 @@
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2021 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package config
import (
"fmt"
"os"
"strings"
"gopkg.in/yaml.v3"
)
type YAMLMap map[string]YAMLNode
type YAMLList []YAMLNode
type YAMLNode struct {
*yaml.Node
Map YAMLMap
List YAMLList
Key *yaml.Node
}
type YAMLType uint32
const (
Null YAMLType = 1 << iota
Bool
Str
Int
Float
Timestamp
List
Map
Binary
)
func (t YAMLType) String() string {
switch t {
case Null:
return NullTag
case Bool:
return BoolTag
case Str:
return StrTag
case Int:
return IntTag
case Float:
return FloatTag
case Timestamp:
return TimestampTag
case List:
return SeqTag
case Map:
return MapTag
case Binary:
return BinaryTag
default:
panic(fmt.Errorf("can't convert type %d to string", t))
}
}
func tagToType(tag string) YAMLType {
switch tag {
case NullTag:
return Null
case BoolTag:
return Bool
case StrTag:
return Str
case IntTag:
return Int
case FloatTag:
return Float
case TimestampTag:
return Timestamp
case SeqTag:
return List
case MapTag:
return Map
case BinaryTag:
return Binary
default:
return 0
}
}
const (
NullTag = "!!null"
BoolTag = "!!bool"
StrTag = "!!str"
IntTag = "!!int"
FloatTag = "!!float"
TimestampTag = "!!timestamp"
SeqTag = "!!seq"
MapTag = "!!map"
BinaryTag = "!!binary"
)
func fromNode(node, key *yaml.Node) YAMLNode {
switch node.Kind {
case yaml.DocumentNode:
return fromNode(node.Content[0], nil)
case yaml.AliasNode:
return fromNode(node.Alias, nil)
case yaml.MappingNode:
return YAMLNode{
Node: node,
Map: parseYAMLMap(node),
Key: key,
}
case yaml.SequenceNode:
return YAMLNode{
Node: node,
List: parseYAMLList(node),
}
default:
return YAMLNode{Node: node, Key: key}
}
}
func (yn *YAMLNode) toNode() *yaml.Node {
switch {
case yn.Map != nil && yn.Node.Kind == yaml.MappingNode:
yn.Content = yn.Map.toNodes()
case yn.List != nil && yn.Node.Kind == yaml.SequenceNode:
yn.Content = yn.List.toNodes()
}
return yn.Node
}
func parseYAMLList(node *yaml.Node) YAMLList {
data := make(YAMLList, len(node.Content))
for i, item := range node.Content {
data[i] = fromNode(item, nil)
}
return data
}
func (yl YAMLList) toNodes() []*yaml.Node {
nodes := make([]*yaml.Node, len(yl))
for i, item := range yl {
nodes[i] = item.toNode()
}
return nodes
}
func parseYAMLMap(node *yaml.Node) YAMLMap {
if len(node.Content)%2 != 0 {
panic(fmt.Errorf("uneven number of items in YAML map (%d)", len(node.Content)))
}
data := make(YAMLMap, len(node.Content)/2)
for i := 0; i < len(node.Content); i += 2 {
key := node.Content[i]
value := node.Content[i+1]
if key.Kind == yaml.ScalarNode {
data[key.Value] = fromNode(value, key)
}
}
return data
}
func (ym YAMLMap) toNodes() []*yaml.Node {
nodes := make([]*yaml.Node, len(ym)*2)
i := 0
for key, value := range ym {
nodes[i] = makeStringNode(key)
nodes[i+1] = value.toNode()
i += 2
}
return nodes
}
func makeStringNode(val string) *yaml.Node {
var node yaml.Node
node.SetString(val)
return &node
}
type UpgradeHelper struct {
base YAMLNode
cfg YAMLNode
}
func NewUpgradeHelper(base, cfg *yaml.Node) *UpgradeHelper {
return &UpgradeHelper{
base: fromNode(base, nil),
cfg: fromNode(cfg, nil),
}
}
func (helper *UpgradeHelper) Copy(allowedTypes YAMLType, path ...string) {
base, cfg := helper.base, helper.cfg
var ok bool
for _, item := range path {
base = base.Map[item]
cfg, ok = cfg.Map[item]
if !ok {
return
}
}
if allowedTypes&tagToType(cfg.Tag) == 0 {
_, _ = fmt.Fprintf(os.Stderr, "Ignoring incorrect config field type %s at %s\n", cfg.Tag, strings.Join(path, "->"))
return
}
base.Tag = cfg.Tag
base.Style = cfg.Style
switch base.Kind {
case yaml.ScalarNode:
base.Value = cfg.Value
case yaml.SequenceNode, yaml.MappingNode:
base.Content = cfg.Content
}
}
func getNode(cfg YAMLNode, path []string) *YAMLNode {
var ok bool
for _, item := range path {
cfg, ok = cfg.Map[item]
if !ok {
return nil
}
}
return &cfg
}
func (helper *UpgradeHelper) GetNode(path ...string) *YAMLNode {
return getNode(helper.cfg, path)
}
func (helper *UpgradeHelper) GetBaseNode(path ...string) *YAMLNode {
return getNode(helper.base, path)
}
func (helper *UpgradeHelper) Get(tag YAMLType, path ...string) (string, bool) {
node := helper.GetNode(path...)
if node == nil || node.Kind != yaml.ScalarNode || tag&tagToType(node.Tag) == 0 {
return "", false
}
return node.Value, true
}
func (helper *UpgradeHelper) GetBase(path ...string) string {
return helper.GetBaseNode(path...).Value
}
func (helper *UpgradeHelper) Set(tag YAMLType, value string, path ...string) {
base := helper.base
for _, item := range path {
base = base.Map[item]
}
base.Tag = tag.String()
base.Value = value
}
func (helper *UpgradeHelper) SetMap(value YAMLMap, path ...string) {
base := helper.base
for _, item := range path {
base = base.Map[item]
}
if base.Tag != MapTag || base.Kind != yaml.MappingNode {
panic(fmt.Errorf("invalid target for SetMap(%+v): tag:%s, kind:%d", path, base.Tag, base.Kind))
}
base.Content = value.toNodes()
}

11
main.go
View file

@ -44,6 +44,7 @@ import (
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"maunium.net/go/mautrix/util/configupgrade"
"maunium.net/go/mautrix-whatsapp/config"
"maunium.net/go/mautrix-whatsapp/database"
@ -126,9 +127,9 @@ func (bridge *Bridge) GenerateRegistration() {
os.Exit(21)
}
err = config.Mutate(*configPath, func(helper *config.UpgradeHelper) {
helper.Set(config.Str, bridge.Config.AppService.ASToken, "appservice", "as_token")
helper.Set(config.Str, bridge.Config.AppService.HSToken, "appservice", "hs_token")
err = config.Mutate(*configPath, func(helper *configupgrade.Helper) {
helper.Set(configupgrade.Str, bridge.Config.AppService.ASToken, "appservice", "as_token")
helper.Set(configupgrade.Str, bridge.Config.AppService.HSToken, "appservice", "hs_token")
})
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "Failed to save config:", err)
@ -405,8 +406,8 @@ func (bridge *Bridge) ResendBridgeInfo() {
if *dontSaveConfig {
bridge.Log.Warnln("Not setting resend_bridge_info to false in config due to --no-update flag")
} else {
err := config.Mutate(*configPath, func(helper *config.UpgradeHelper) {
helper.Set(config.Bool, "false", "bridge", "resend_bridge_info")
err := config.Mutate(*configPath, func(helper *configupgrade.Helper) {
helper.Set(configupgrade.Bool, "false", "bridge", "resend_bridge_info")
})
if err != nil {
bridge.Log.Errorln("Failed to save config after setting resend_bridge_info to false:", err)