feat: switch to toml for config (#67)
* feat: switch to toml for config * resolve indirect dep
This commit is contained in:
parent
b0ca25677f
commit
7c140afb03
6 changed files with 119 additions and 127 deletions
44
README.md
44
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
|
||||
|
||||
|
|
|
|||
159
config.go
159
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
1
go.mod
1
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
|
||||
|
|
|
|||
2
go.sum
2
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=
|
||||
|
|
|
|||
22
main.go
22
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()
|
||||
|
|
|
|||
18
ui.go
18
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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue