-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.go
More file actions
88 lines (76 loc) 路 2.64 KB
/
Copy pathconfig.go
File metadata and controls
88 lines (76 loc) 路 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// Config holds all settings needed to run the absence bot, loaded from a
// local YAML file (see config.example.yaml).
type Config struct {
Homeserver string `yaml:"homeserver"`
UserID string `yaml:"user_id"`
AccessToken string `yaml:"access_token"`
DeviceID string `yaml:"device_id"`
// PickleKey encrypts the local crypto store at rest. Keep it secret and
// stable across restarts - changing it makes the existing crypto.db
// unreadable.
PickleKey string `yaml:"pickle_key"`
// RecoveryKey is the account's SSSS recovery key. Optional, but without
// it the bot's device may never be trusted by your other devices, which
// means it may never receive the keys needed to decrypt messages in
// encrypted rooms.
RecoveryKey string `yaml:"recovery_key"`
CryptoDBPath string `yaml:"crypto_db_path"`
StatePath string `yaml:"state_path"`
ReplyMessage string `yaml:"reply_message"`
// Presence is sent as set_presence on every /sync request, so it's what
// makes you show up as "away" to others while the bot runs - without it,
// the mere act of the bot polling /sync marks you "online" on every
// request, regardless of what the auto-reply says. One of "unavailable"
// (shown as "Away" in most clients - the default), "offline", or
// "online" (to leave your real presence alone and only use the
// auto-reply).
Presence string `yaml:"presence"`
}
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read config file %q: %w", path, err)
}
cfg := &Config{
CryptoDBPath: "crypto.db",
StatePath: "state.json",
ReplyMessage: "I'm currently away and will get back to you as soon as I can.",
Presence: "unavailable",
}
if err := yaml.Unmarshal(data, cfg); err != nil {
return nil, fmt.Errorf("failed to parse config file %q: %w", path, err)
}
if err := cfg.validate(); err != nil {
return nil, err
}
return cfg, nil
}
func (c *Config) validate() error {
missing := func(name, val string) string {
if val == "" {
return name + " "
}
return ""
}
problems := missing("homeserver", c.Homeserver) +
missing("user_id", c.UserID) +
missing("access_token", c.AccessToken) +
missing("device_id", c.DeviceID) +
missing("pickle_key", c.PickleKey) +
missing("reply_message", c.ReplyMessage)
if problems != "" {
return fmt.Errorf("config is missing required field(s): %s", problems)
}
switch c.Presence {
case "online", "offline", "unavailable":
default:
return fmt.Errorf("presence must be one of \"online\", \"offline\", \"unavailable\", got %q", c.Presence)
}
return nil
}