diff --git a/README.md b/README.md index 2a35513..7a0a86e 100644 --- a/README.md +++ b/README.md @@ -39,51 +39,11 @@ sudo mv ./discordo /usr/local/bin 1. Run the `discordo` executable with no arguments in a new Terminal window. 2. Log in using the account email and password (first-time login) and click on the "Login" button to continue. -> By default, Discordo utilizes OS-specific keyring to store credentials such as client authentication token. However, if you prefer not to use a keyring, you may set the `token` field in the configuration file (`~/.config/discordo/config.json`) and Discordo will prioritize the usage of `Token` field to login instead of keyring. +> By default, Discordo utilizes OS-specific keyring to store credentials such as client authentication token. However, if you prefer not to use a keyring (not recommended), you may set the `token` field in the configuration file (`~/.config/discordo/config.toml`) and Discordo will prioritize the usage of the provided token to login instead of keyring. ### Configuration -Discordo aims to be highly configurable, it may be easily customized via a configuration file. It creates a default configuration file on the first start-up. The default and newly created configuration file is located at `$HOME/.config/discordo/config.json`. Here is a sample (not default) configuration file: - -```jsonc -{ - // The client authentication token (optional) - "Token": "", - // Enables mouse support. - "Mouse": true, - // Enables OS-specific desktop notifications when the client user is mentioned in non-selected channels. - "Notifications": true, - // Set a custom user agent for all of the HTTP requests. - "UserAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36", - // Set the number of messages to retrieve when a text-based channel is selected. - "GetMessagesLimit": 30, - // The Theme field values can be hex color codes (#f44f36) or W3C color names. - "Theme": { - "PrimitiveBackgroundColor": "black", - "ContrastBackgroundColor": "blue", - "MoreContrastBackgroundColor": "green", - "BorderColor": "white", - "TitleColor": "white", - "GraphicsColor": "white", - "PrimaryTextColor": "white", - "SecondaryTextColor": "yellow", - "TertiaryTextColor": "green", - "InverseTextColor": "blue", - "ContrastSecondaryTextColor": "darkcyan" - }, - "Keybindings": { - "GuildsTreeViewFocus": "Alt+Rune[1]", - "MessagesTextViewFocus": "Alt+Rune[2]", - "MessagesTextViewSelectPrevious": "Up", - "MessagesTextViewSelectNext": "Down", - "MessagesTextViewSelectFirst": "Home", - "MessagesTextViewSelectLast": "End", - "MessagesTextViewReplySelected": "Rune[r]", - "MessagesTextViewMentionReplySelected": "Rune[R]", - "MessageInputFieldFocus": "Alt+Rune[3]" - } -} -``` +Discordo aims to be highly configurable, it may be easily customized via a configuration file. It creates a default configuration file on the first start-up. The default and newly created configuration file is located at `$HOME/.config/discordo/config.toml`. ### Clipboard support diff --git a/config.go b/config.go index f84a9a5..c110fca 100644 --- a/config.go +++ b/config.go @@ -1,48 +1,79 @@ package main import ( - "encoding/json" "os" + + "github.com/BurntSushi/toml" ) var conf *config +type keybindingsChannelsTree struct { + Focus string `toml:"focus"` +} + +type keybindingsMessagesTextView struct { + Focus string `toml:"focus"` + SelectPrevious string `toml:"select_previous"` + SelectNext string `toml:"select_next"` + SelectFirst string `toml:"select_first"` + SelectLast string `toml:"select_last"` + Reply string `toml:"reply"` + ReplyMention string `toml:"reply_mention"` +} + +type keybindingsMessageInputField struct { + Focus string `toml:"focus"` +} + type keybindings struct { - GuildsTreeViewFocus string + ChannelsTree keybindingsChannelsTree `toml:"channels_tree"` + MessagesTextView keybindingsMessagesTextView `toml:"messages_textview"` + MessageInputField keybindingsMessageInputField `toml:"message_inputfield"` +} - MessagesTextViewFocus string - MessagesTextViewSelectPrevious string - MessagesTextViewSelectNext string - MessagesTextViewSelectFirst string - MessagesTextViewSelectLast string - MessagesTextViewReplySelected string - MessagesTextViewMentionReplySelected string +type themeBackground struct { + // Main background color for primitives. + Primitive string `toml:"primitive"` + // Background color for contrasting elements. + Contrast string `toml:"contrast"` + // Background color for even more contrasting elements. + MoreContrast string `toml:"more_contrast"` +} - MessageInputFieldFocus string +type themeText struct { + // Primary text. + Primary string `toml:"primary"` + // Secondary text (e.g. labels). + Secondary string `toml:"secondary"` + // Tertiary text (e.g. subtitles, notes). + Tertiary string `toml:"tertiary"` + // Text on primary-colored backgrounds. + Inverse string `toml:"inverse"` + // Secondary text on ContrastBackgroundColor-colored backgrounds. + ContrastSecondary string `toml:"contrast_secondary"` } type theme struct { - PrimitiveBackgroundColor string // Main background color for primitives. - ContrastBackgroundColor string // Background color for contrasting elements. - MoreContrastBackgroundColor string // Background color for even more contrasting elements. - BorderColor string // Box borders. - TitleColor string // Box titles. - GraphicsColor string // Graphics. - PrimaryTextColor string // Primary text. - SecondaryTextColor string // Secondary text (e.g. labels). - TertiaryTextColor string // Tertiary text (e.g. subtitles, notes). - InverseTextColor string // Text on primary-colored backgrounds. - ContrastSecondaryTextColor string // Secondary text on ContrastBackgroundColor-colored backgrounds. + // Box borders. + Border string `toml:"border"` + // Box titles. + Title string `toml:"title"` + // Graphics. + Graphics string `toml:"graphics"` + + Background themeBackground `toml:"background"` + Text themeText `toml:"text"` } type config struct { - Token string - Mouse bool - Notifications bool - UserAgent string - GetMessagesLimit int - Theme theme - Keybindings keybindings + Token string `toml:"token"` + Mouse bool `toml:"mouse"` + Notifications bool `toml:"notifications"` + UserAgent string `toml:"user_agent"` + GetMessagesLimit int `toml:"get_messages_limit"` + Theme theme `toml:"theme"` + Keybindings keybindings `toml:"keybindings"` } func loadConfig() *config { @@ -51,7 +82,7 @@ func loadConfig() *config { panic(err) } - configPath := u + "/.config/discordo/config.json" + configPath := u + "/.config/discordo/config.toml" if _, err = os.Stat(configPath); os.IsNotExist(err) { err = os.MkdirAll(u+"/.config/discordo", 0700) if err != nil { @@ -73,54 +104,52 @@ func loadConfig() *config { "Chrome/92.0.4515.131 Safari/537.36", GetMessagesLimit: 50, Theme: theme{ - PrimitiveBackgroundColor: "black", - ContrastBackgroundColor: "blue", - MoreContrastBackgroundColor: "green", - BorderColor: "white", - TitleColor: "white", - GraphicsColor: "white", - PrimaryTextColor: "white", - SecondaryTextColor: "yellow", - TertiaryTextColor: "green", - InverseTextColor: "blue", - ContrastSecondaryTextColor: "darkcyan", + Border: "white", + Title: "white", + Graphics: "white", + Background: themeBackground{ + Primitive: "black", + Contrast: "blue", + MoreContrast: "green", + }, + Text: themeText{ + Primary: "white", + Secondary: "yellow", + Tertiary: "green", + Inverse: "blue", + ContrastSecondary: "darkcyan", + }, }, Keybindings: keybindings{ - GuildsTreeViewFocus: "Alt+Rune[1]", - - MessagesTextViewFocus: "Alt+Rune[2]", - MessagesTextViewSelectPrevious: "Up", - MessagesTextViewSelectNext: "Down", - MessagesTextViewSelectFirst: "Home", - MessagesTextViewSelectLast: "End", - MessagesTextViewReplySelected: "Rune[r]", - MessagesTextViewMentionReplySelected: "Rune[R]", - - MessageInputFieldFocus: "Alt+Rune[3]", + ChannelsTree: keybindingsChannelsTree{ + Focus: "Alt+Rune[1]", + }, + MessagesTextView: keybindingsMessagesTextView{ + Focus: "Alt+Rune[2]", + SelectPrevious: "Up", + SelectNext: "Down", + SelectFirst: "Home", + SelectLast: "End", + Reply: "Rune[r]", + ReplyMention: "Rune[R]", + }, + MessageInputField: keybindingsMessageInputField{ + Focus: "Alt+Rune[3]", + }, }, } - d, err := json.MarshalIndent(c, "", "\t") + + err = toml.NewEncoder(f).Encode(c) if err != nil { panic(err) } - _, err = f.Write(d) - if err != nil { - panic(err) - } - - f.Sync() - return &c } - d, err := os.ReadFile(configPath) - if err != nil { - panic(err) - } - var c config - if err = json.Unmarshal(d, &c); err != nil { + _, err = toml.DecodeFile(configPath, &c) + if err != nil { panic(err) } diff --git a/go.mod b/go.mod index 7981881..fca8958 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/ayntgl/discordo go 1.16 require ( + github.com/BurntSushi/toml v0.4.1 github.com/atotto/clipboard v0.1.4 github.com/ayntgl/discordgo v0.23.3-0.20210920064905-b79d709bbafb github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1 diff --git a/go.sum b/go.sum index 4ea87b1..ba3e2fe 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= +github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/ayntgl/discordgo v0.23.3-0.20210920064905-b79d709bbafb h1:4WL/2+MpUEvYl5shkF4YpNJAT7MG/JXR1p/6DnJ3GPY= diff --git a/main.go b/main.go index 057a22f..27db595 100644 --- a/main.go +++ b/main.go @@ -11,17 +11,17 @@ const service = "discordo" func main() { conf = loadConfig() - tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(conf.Theme.PrimitiveBackgroundColor) - tview.Styles.ContrastBackgroundColor = tcell.GetColor(conf.Theme.ContrastBackgroundColor) - tview.Styles.MoreContrastBackgroundColor = tcell.GetColor(conf.Theme.MoreContrastBackgroundColor) - tview.Styles.BorderColor = tcell.GetColor(conf.Theme.BorderColor) - tview.Styles.TitleColor = tcell.GetColor(conf.Theme.TitleColor) - tview.Styles.GraphicsColor = tcell.GetColor(conf.Theme.GraphicsColor) - tview.Styles.PrimaryTextColor = tcell.GetColor(conf.Theme.PrimaryTextColor) - tview.Styles.SecondaryTextColor = tcell.GetColor(conf.Theme.SecondaryTextColor) - tview.Styles.TertiaryTextColor = tcell.GetColor(conf.Theme.TertiaryTextColor) - tview.Styles.InverseTextColor = tcell.GetColor(conf.Theme.InverseTextColor) - tview.Styles.ContrastSecondaryTextColor = tcell.GetColor(conf.Theme.ContrastSecondaryTextColor) + tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(conf.Theme.Background.Primitive) + tview.Styles.ContrastBackgroundColor = tcell.GetColor(conf.Theme.Background.Contrast) + tview.Styles.MoreContrastBackgroundColor = tcell.GetColor(conf.Theme.Background.MoreContrast) + tview.Styles.BorderColor = tcell.GetColor(conf.Theme.Border) + tview.Styles.TitleColor = tcell.GetColor(conf.Theme.Title) + tview.Styles.GraphicsColor = tcell.GetColor(conf.Theme.Graphics) + tview.Styles.PrimaryTextColor = tcell.GetColor(conf.Theme.Text.Primary) + tview.Styles.SecondaryTextColor = tcell.GetColor(conf.Theme.Text.Secondary) + tview.Styles.TertiaryTextColor = tcell.GetColor(conf.Theme.Text.Tertiary) + tview.Styles.InverseTextColor = tcell.GetColor(conf.Theme.Text.Inverse) + tview.Styles.ContrastSecondaryTextColor = tcell.GetColor(conf.Theme.Text.ContrastSecondary) app = newApplication() channelsTree = newChannelsTree() diff --git a/ui.go b/ui.go index 079603c..f3fdfa6 100644 --- a/ui.go +++ b/ui.go @@ -29,11 +29,11 @@ func newApplication() *tview.Application { func onAppInputCapture(e *tcell.EventKey) *tcell.EventKey { switch e.Name() { - case conf.Keybindings.GuildsTreeViewFocus: + case conf.Keybindings.ChannelsTree.Focus: app.SetFocus(channelsTree) - case conf.Keybindings.MessagesTextViewFocus: + case conf.Keybindings.MessagesTextView.Focus: app.SetFocus(messagesTextView) - case conf.Keybindings.MessageInputFieldFocus: + case conf.Keybindings.MessageInputField.Focus: app.SetFocus(messageInputField) } @@ -226,7 +226,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { } switch e.Name() { - case conf.Keybindings.MessagesTextViewSelectPrevious: + case conf.Keybindings.MessagesTextView.SelectPrevious: ms := selectedChannel.Messages if len(ms) == 0 { return nil @@ -249,7 +249,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { } return nil - case conf.Keybindings.MessagesTextViewSelectNext: + case conf.Keybindings.MessagesTextView.SelectNext: ms := selectedChannel.Messages if len(ms) == 0 { return nil @@ -272,7 +272,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { } return nil - case conf.Keybindings.MessagesTextViewSelectFirst: + case conf.Keybindings.MessagesTextView.SelectFirst: ms := selectedChannel.Messages if len(ms) == 0 { return nil @@ -281,7 +281,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { messagesTextView. Highlight(ms[0].ID). ScrollToHighlight() - case conf.Keybindings.MessagesTextViewSelectLast: + case conf.Keybindings.MessagesTextView.SelectLast: ms := selectedChannel.Messages if len(ms) == 0 { return nil @@ -290,7 +290,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { messagesTextView. Highlight(ms[len(ms)-1].ID). ScrollToHighlight() - case conf.Keybindings.MessagesTextViewReplySelected: + case conf.Keybindings.MessagesTextView.Reply: ms := selectedChannel.Messages if len(ms) == 0 { return nil @@ -306,7 +306,7 @@ func onMessagesTextViewInputCapture(e *tcell.EventKey) *tcell.EventKey { "Replying to " + selectedMessage.Author.Username, ) app.SetFocus(messageInputField) - case conf.Keybindings.MessagesTextViewMentionReplySelected: + case conf.Keybindings.MessagesTextView.ReplyMention: ms := selectedChannel.Messages if len(ms) == 0 { return nil