Merge branch 'main' into add-nix

This commit is contained in:
Emanuel Johnson Godin 2025-05-26 19:17:06 +02:00 • committed by GitHub
commit 0dd45a3fbc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 176 additions and 179 deletions

View file

@ -55,46 +55,6 @@ go build .
2. Enter your email and password and click on the "Login" button to continue.
## Keymaps
### Global
- `Ctrl+G`: Focus Guilds Tree
- `Ctrl+T`: Focus Messages Text
- `Ctrl+P`: Focus Message Input
- `Ctrl+B`: Toggle Guilds Tree (sidebar)
- `Esc`: Reset message selection or close the channel selection popup.
- `Ctrl+C`: Quit the application.
- `Ctrl+D`: Log out and remove the authentication token from keyring (requires re-login upon restart).
#### Navigation
- `k`: Select Previous (any context except input)
- `j`: Select Next (any context except input)
- `g`: Select First (any context except input)
- `G`: Select Last (any context except input)
### Guilds Tree
- `Enter`: Select the currently highlighted text-based channel or expand a guild or channel.
### Message Text
- `s`: Select the message reference (reply) of the selected channel.
- `p`: Select the pinned message.
- `r`: Reply to the selected message.
- `R`: Reply (with mention) to the selected message.
- `d`: Delete the selected message.
- `y`: Yank (copy) the selected message's content.
- `o`: Open the selected message's attachments in the default browser application.
### Message Input
- `Alt+Enter`: Insert a new line to the current text.
- `Enter`: Send the message.
- `Ctrl+E`: Open message input in your default `$EDITOR`.
- `Esc`: Remove existing text or cancel reply.
## Configuration
The configuration file allows you to configure and customize the behavior, keybindings, and theme of the application.
@ -103,7 +63,7 @@ The configuration file allows you to configure and customize the behavior, keybi
- Darwin: `$HOME/Library/Application Support/discordo/config.toml`
- Windows: `%AppData%/discordo/config.toml`
[The default configuration can be found here](./internal/config/config.go).
[The default configuration can be found here](./internal/config/config.toml).
## FAQ

View file

@ -20,6 +20,11 @@ var (
func Run() error {
logLevel := flag.String("log-level", "info", "log level")
logFormat := flag.String("log-format", "text", "log format")
token := flag.String("token", "", "authentication token")
configPath := flag.String("config", config.DefaultPath(), "path to the configuration file")
flag.Parse()
var level slog.Level
switch *logLevel {
case "debug":
@ -33,7 +38,6 @@ func Run() error {
level = slog.LevelError
}
logFormat := flag.String("log-format", "text", "log format")
var format logger.Format
switch *logFormat {
case "text":
@ -46,7 +50,6 @@ func Run() error {
return err
}
token := flag.String("token", "", "authentication token")
tok := *token
if tok == "" {
var err error
@ -56,7 +59,7 @@ func Run() error {
}
}
cfg, err := config.Load()
cfg, err := config.Load(*configPath)
if err != nil {
return err
}

View file

@ -19,6 +19,8 @@ func (p *BorderPreset) UnmarshalTOML(v any) error {
*p = borderPresetThick()
case "round":
*p = borderPresetRound()
case "light":
*p = borderPresetLight()
case "hidden":
*p = BorderPreset{
Horizontal: ' ',
@ -65,3 +67,14 @@ func borderPresetRound() BorderPreset {
BottomRight: tview.BoxDrawingsLightArcUpAndLeft,
}
}
func borderPresetLight() BorderPreset {
return BorderPreset{
Horizontal: tview.BoxDrawingsLightHorizontal,
Vertical: tview.BoxDrawingsLightVertical,
TopLeft: tview.BoxDrawingsLightDownAndRight,
TopRight: tview.BoxDrawingsLightDownAndLeft,
BottomLeft: tview.BoxDrawingsLightUpAndRight,
BottomRight: tview.BoxDrawingsLightUpAndLeft,
}
}

View file

@ -1,10 +1,10 @@
package config
import (
_ "embed"
"log/slog"
"os"
"path/filepath"
"time"
"github.com/BurntSushi/toml"
"github.com/ayn2op/discordo/internal/consts"
@ -56,57 +56,31 @@ type (
}
)
func defaultConfig() *Config {
return &Config{
Mouse: true,
Editor: "default",
//go:embed config.toml
var defaultCfg []byte
HideBlockedUsers: true,
ShowAttachmentLinks: true,
MessagesLimit: 50,
MarkdownEnabled: true,
Timestamps: Timestamps{
Enabled: true,
Format: time.Kitchen,
},
Identify: Identify{
Status: discord.OnlineStatus,
Browser: consts.Browser,
BrowserVersion: consts.BrowserVersion,
UserAgent: consts.UserAgent,
},
Notifications: Notifications{
Enabled: true,
Duration: 500,
Sound: Sound{
Enabled: true,
OnlyOnPing: true,
},
},
Keys: defaultKeys(),
Theme: defaultTheme(),
}
}
// Reads the configuration file and parses it.
func Load() (*Config, error) {
func DefaultPath() string {
path, err := os.UserConfigDir()
if err != nil {
slog.Info("user configuration directory path cannot be determined; falling back to the current directory path")
path = "."
}
path = filepath.Join(path, consts.Name, fileName)
return filepath.Join(path, consts.Name, fileName)
}
// Reads the configuration file and parses it.
func Load(path string) (*Config, error) {
f, err := os.Open(path)
cfg := defaultConfig()
var cfg *Config
if err := toml.Unmarshal(defaultCfg, &cfg); err != nil {
return nil, err
}
if os.IsNotExist(err) {
slog.Info("the configuration file does not exist, falling back to the default configuration", "path", path, "err", err)
handleDefaults(cfg)
return cfg, nil
}
@ -119,5 +93,18 @@ func Load() (*Config, error) {
return nil, err
}
handleDefaults(cfg)
return cfg, nil
}
func handleDefaults(cfg *Config) {
if cfg.Identify.Browser == "default" {
cfg.Identify.Browser = consts.Browser
}
if cfg.Identify.BrowserVersion == "default" {
cfg.Identify.BrowserVersion = consts.BrowserVersion
}
if cfg.Identify.UserAgent == "default" {
cfg.Identify.UserAgent = consts.UserAgent
}
}

128
internal/config/config.toml Normal file
View file

@ -0,0 +1,128 @@
# Enable mouse controls
mouse = true
# "default" means use $EDITOR.
editor = "default"
hide_blocked_users = true
show_attachment_links = true
messages_limit = 50
markdown_enabled = true
# Timestamps uses Go timestamp format
# See: https://gosamples.dev/date-time-format-cheatsheet
[timestamps]
enabled = true
format = "3:04PM"
[notifications]
enabled = true
duration = 500
[notifications.sound]
enabled = true
only_on_ping = true
# How Discord sees us.
# status: "online", "idle", "dnd" (Do Not Disturb), "" (invisible),
# note: does not seem to work
[identify]
status = "online"
browser = "default"
browser_version = "default"
user_agent = "default"
# Global shortcuts
# Esc: Reset message selection or close the channel selection popup.
[keys]
focus_guilds_tree = "Ctrl+G"
focus_messages_text = "Ctrl+T"
focus_message_input = "Ctrl+P"
# Hide/show the guilds tree
toggle_guilds_tree = "Ctrl+B"
quit = "Ctrl+C"
# Log out and remove the authentication token from keyring.
# Requires re-login upon restart.
logout = "Ctrl+D"
# Only while focusing on the guilds tree
[keys.guilds_tree]
select_previous = "Rune[k]"
select_next = "Rune[j]"
select_first = "Rune[g]"
select_last = "Rune[G]"
# Select the currently highlighted text-based channel or expand a guild or channel.
select_current = "Enter"
yank_id = "Rune[i]"
collapse_parent_node = "Rune[-]"
move_to_parent_node = "Rune[p]"
# Only while focusing on sent messages
[keys.messages_text]
select_previous = "Rune[k]"
select_next = "Rune[j]"
select_first = "Rune[g]"
select_last = "Rune[G]"
# Select the message reference (reply) of the selected channel.
select_reply = "Rune[s]"
# Reply to the selected message.
reply = "Rune[r]"
# Reply (with mention) to the selected message.
reply_mention = "Rune[R]"
cancel = "Esc"
delete = "Rune[d]"
# Open the selected message's attachments or hyperlinks in the message
# using the default browser application.
open = "Rune[o]"
# Yank (copy) the selected message's content/url/id.
yank_content = "Rune[y]"
yank_url = "Rune[u]"
yank_id = "Rune[i]"
# Only while typing a message
# Alt+Enter: Insert a new line to the current text.
[keys.message_input]
# Send the message.
send = "Enter"
# Open message input in your editor.
editor = "Ctrl+E"
# Remove existing text or cancel reply.
cancel = "Esc"
# Applies to all
[theme]
background_color = "default"
[theme.title]
# Title color of non-focused widgets
color = "default"
# Title color of the focused widget
active_color = "green"
align = "left"
[theme.border]
enabled = true
# [top, bottom, left, right]
padding = [0, 0, 1, 1]
color = "default"
active_color = "green"
preset = "round"
[theme.guilds_tree]
auto_expand_folders = true
# Give tree-like shape
graphics = true
private_channel_color = "white"
guild_color = "white"
channel_color = "white"
[theme.messages_text]
# Set to false to show messages with usernames instead of nicknames
show_user_nicks = true
show_user_colors = true
reply_indicator = ">"
forwarded_indicator = "<"
author_color = "aqua"
content_color = "white"
emoji_color = "green"
link_color = "blue"
attachment_color = "yellow"

View file

@ -52,55 +52,3 @@ type (
Cancel string `toml:"cancel"`
}
)
func defaultKeys() Keys {
return Keys{
FocusGuildsTree: "Ctrl+G",
FocusMessagesText: "Ctrl+T",
FocusMessageInput: "Ctrl+P",
ToggleGuildsTree: "Ctrl+B",
Logout: "Ctrl+D",
Quit: "Ctrl+C",
GuildsTree: GuildsTreeKeys{
NavigationKeys: NavigationKeys{
SelectPrevious: "Rune[k]",
SelectNext: "Rune[j]",
SelectFirst: "Rune[g]",
SelectLast: "Rune[G]",
},
SelectCurrent: "Enter",
YankID: "Rune[i]",
CollapseParentNode: "Rune[-]",
MoveToParentNode: "Rune[p]",
},
MessagesText: MessagesTextKeys{
NavigationKeys: NavigationKeys{
SelectPrevious: "Rune[k]",
SelectNext: "Rune[j]",
SelectFirst: "Rune[g]",
SelectLast: "Rune[G]",
},
SelectReply: "Rune[s]",
Reply: "Rune[r]",
ReplyMention: "Rune[R]",
Cancel: "Esc",
Delete: "Rune[d]",
Open: "Rune[o]",
YankContent: "Rune[y]",
YankURL: "Rune[u]",
YankID: "Rune[i]",
},
MessageInput: MessageInputKeys{
Send: "Enter",
Editor: "Ctrl+E",
Cancel: "Esc",
},
}
}

View file

@ -68,45 +68,3 @@ type (
AttachmentColor string `toml:"attachment_color"`
}
)
func defaultTheme() Theme {
return Theme{
BackgroundColor: "default",
Border: BorderTheme{
Enabled: true,
Padding: [...]int{0, 0, 1, 1},
Color: "default",
ActiveColor: "green",
Preset: borderPresetRound(),
},
Title: TitleTheme{
Color: "default",
ActiveColor: "green",
Align: tview.AlignLeft,
},
GuildsTree: GuildsTreeTheme{
AutoExpandFolders: true,
ChannelColor: tview.Styles.PrimaryTextColor.String(),
Graphics: true,
GuildColor: tview.Styles.PrimaryTextColor.String(),
PrivateChannelColor: tview.Styles.PrimaryTextColor.String(),
},
MessagesText: MessagesTextTheme{
ShowNicknames: true,
ShowUsernameColors: true,
ReplyIndicator: ">",
ForwardedIndicator: "<",
AuthorColor: "aqua",
ContentColor: tview.Styles.PrimaryTextColor.String(),
EmojiColor: "green",
LinkColor: "blue",
AttachmentColor: "yellow",
},
}
}