From 42a4839a4ee35c4b5fe683ba73a2e9597e277b97 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 21 May 2022 12:06:07 +0300 Subject: [PATCH] Move config upgrade helper to mautrix-go --- config/upgrade.go | 345 +++++++++++++++++----------------------- config/upgradehelper.go | 278 -------------------------------- main.go | 11 +- 3 files changed, 153 insertions(+), 481 deletions(-) delete mode 100644 config/upgradehelper.go diff --git a/config/upgrade.go b/config/upgrade.go index fa22003..6c6d681 100644 --- a/config/upgrade.go +++ b/config/upgrade.go @@ -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{}) } diff --git a/config/upgradehelper.go b/config/upgradehelper.go deleted file mode 100644 index bb2fd6f..0000000 --- a/config/upgradehelper.go +++ /dev/null @@ -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 . - -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() -} diff --git a/main.go b/main.go index c72b1d6..d83342d 100644 --- a/main.go +++ b/main.go @@ -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)