| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- package config
- import (
- _ "embed"
- "fmt"
- "log/slog"
- "os"
- "path/filepath"
- "strings"
- "unicode/utf8"
- "github.com/BurntSushi/toml"
- "github.com/ayn2op/discordo/internal/consts"
- "github.com/diamondburned/arikawa/v3/discord"
- )
- const fileName = "config.toml"
- type (
- Timestamps struct {
- Enabled bool `toml:"enabled"`
- Format string `toml:"format"`
- }
- DateSeparator struct {
- Enabled bool `toml:"enabled"`
- Format string `toml:"format"`
- Character string `toml:"character"`
- }
- Notifications struct {
- Enabled bool `toml:"enabled"`
- Duration int `toml:"duration"`
- Sound Sound `toml:"sound"`
- }
- Sound struct {
- Enabled bool `toml:"enabled"`
- OnlyOnPing bool `toml:"only_on_ping"`
- }
- TypingIndicator struct {
- Send bool `toml:"send"`
- Receive bool `toml:"receive"`
- }
- Icons struct {
- GuildCategory string `toml:"guild_category"`
- GuildText string `toml:"guild_text"`
- GuildVoice string `toml:"guild_voice"`
- GuildStageVoice string `toml:"guild_stage_voice"`
- GuildAnnouncementThread string `toml:"guild_announcement_thread"`
- GuildPublicThread string `toml:"guild_public_thread"`
- GuildPrivateThread string `toml:"guild_private_thread"`
- GuildAnnouncement string `toml:"guild_announcement"`
- GuildForum string `toml:"guild_forum"`
- GuildStore string `toml:"guild_store"`
- }
- PickerConfig struct {
- Width int `toml:"width"`
- Height int `toml:"height"`
- }
- MarkdownConfig struct {
- Enabled bool `toml:"enabled"`
- Theme string `toml:"theme"`
- }
- HelpConfig struct {
- CompactModifiers bool `toml:"compact_modifiers"`
- Padding [2]int `toml:"padding"`
- Separator string `toml:"separator"`
- }
- SidebarMarkersConfig struct {
- Expanded string `toml:"expanded"`
- Collapsed string `toml:"collapsed"`
- Leaf string `toml:"leaf"`
- }
- SidebarConfig struct {
- Markers SidebarMarkersConfig `toml:"markers"`
- }
- Config struct {
- Path string // set programmatically, not from TOML
- AutoFocus bool `toml:"auto_focus"`
- Mouse bool `toml:"mouse"`
- Editor string `toml:"editor"`
- Status discord.Status `toml:"status"`
- HideBlockedUsers bool `toml:"hide_blocked_users"`
- ShowAttachmentLinks bool `toml:"show_attachment_links"`
- ImageViewer string `toml:"image_viewer"`
- ImageSaveDir string `toml:"image_save_dir"`
- // Use 0 to disable
- AutocompleteLimit uint8 `toml:"autocomplete_limit"`
- MessagesLimit uint8 `toml:"messages_limit"`
- Markdown MarkdownConfig `toml:"markdown"`
- Help HelpConfig `toml:"help"`
- Picker PickerConfig `toml:"picker"`
- Timestamps Timestamps `toml:"timestamps"`
- DateSeparator DateSeparator `toml:"date_separator"`
- Notifications Notifications `toml:"notifications"`
- TypingIndicator TypingIndicator `toml:"typing_indicator"`
- Sidebar SidebarConfig `toml:"sidebar"`
- Icons Icons `toml:"icons"`
- Keybinds Keybinds `toml:"keybinds"`
- Theme Theme `toml:"theme"`
- }
- )
- //go:embed config.toml
- var defaultCfg []byte
- func DefaultPath() string {
- path, err := os.UserConfigDir()
- if err != nil {
- slog.Info(
- "user config dir cannot be determined; falling back to the current dir",
- "err", err,
- )
- path = "."
- }
- return filepath.Join(path, consts.Name, fileName)
- }
- // Load reads the configuration file and parses it.
- func Load(path string) (*Config, error) {
- cfg := Config{
- Keybinds: defaultKeybinds(),
- }
- if err := toml.Unmarshal(defaultCfg, &cfg); err != nil {
- return nil, fmt.Errorf("failed to unmarshal default config: %w", err)
- }
- file, err := os.Open(path)
- if os.IsNotExist(err) {
- slog.Info(
- "config file does not exist, falling back to the default config",
- "path",
- path,
- "err",
- err,
- )
- } else {
- if err != nil {
- return nil, fmt.Errorf("failed to open config file: %w", err)
- }
- defer file.Close()
- if _, err := toml.NewDecoder(file).Decode(&cfg); err != nil {
- return nil, fmt.Errorf("failed to decode config: %w", err)
- }
- }
- cfg.Path = path
- applyDefaults(&cfg)
- return &cfg, nil
- }
- func applyDefaults(cfg *Config) {
- if cfg.Editor == "default" {
- cfg.Editor = os.Getenv("EDITOR")
- }
- if cfg.Status == "default" {
- cfg.Status = discord.UnknownStatus
- }
- if cfg.ImageViewer == "default" {
- cfg.ImageViewer = ""
- }
- if strings.HasPrefix(cfg.ImageSaveDir, "~/") {
- if home, err := os.UserHomeDir(); err == nil {
- cfg.ImageSaveDir = filepath.Join(home, cfg.ImageSaveDir[2:])
- }
- }
- if cfg.DateSeparator.Format == "" {
- cfg.DateSeparator.Format = "January 2, 2006"
- }
- if cfg.DateSeparator.Character == "" {
- cfg.DateSeparator.Character = "─"
- return
- }
- r, _ := utf8.DecodeRuneInString(cfg.DateSeparator.Character)
- if r == utf8.RuneError {
- cfg.DateSeparator.Character = "─"
- return
- }
- cfg.DateSeparator.Character = string(r)
- }
|