refactor: modularize into packages
This commit is contained in:
parent
2a40b68648
commit
548c9f0007
11 changed files with 167 additions and 298 deletions
|
|
@ -38,11 +38,9 @@ sudo mv ./discordo /usr/local/bin
|
|||
|
||||
1. Run the `discordo` executable with no arguments.
|
||||
|
||||
> On first startup, a default configuration file will be created at `$HOME/.config/discordo.toml` on Unix, `%AppData%/discordo.toml` on Windows, and `$HOME/Library/Application Support/discordo.toml` on Darwin.
|
||||
|
||||
2. Log in using the account email and password (first-time login) and click on the "Login" button to continue.
|
||||
|
||||
> Note: 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 and Discordo will prioritize the usage of the provided token to login instead of keyring.
|
||||
> Note: 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 `DISCORDO_TOKEN` environment variable and Discordo will prioritize the usage of the provided token to login instead of keyring.
|
||||
|
||||
### Clipboard support
|
||||
|
||||
|
|
|
|||
41
config/config.go
Normal file
41
config/config.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package config
|
||||
|
||||
var General = struct {
|
||||
UserAgent string
|
||||
Mouse bool
|
||||
Notifications bool
|
||||
FetchMessagesLimit int
|
||||
}{
|
||||
UserAgent: "Mozilla/5.0 (X11; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0",
|
||||
Mouse: true,
|
||||
Notifications: true,
|
||||
FetchMessagesLimit: 50,
|
||||
}
|
||||
|
||||
var Keybindings = struct {
|
||||
FocusChannelsTreeView []string
|
||||
FocusMessagesView []string
|
||||
FocusMessageInputField []string
|
||||
|
||||
SelectPreviousMessage []string
|
||||
SelectNextMessage []string
|
||||
SelectFirstMessage []string
|
||||
SelectLastMessage []string
|
||||
SelectMessageReference []string
|
||||
ReplySelectedMessage []string
|
||||
MentionReplySelectedMessage []string
|
||||
CopySelectedMessage []string
|
||||
}{
|
||||
FocusChannelsTreeView: []string{"Alt+Left"},
|
||||
FocusMessagesView: []string{"Alt+Right"},
|
||||
FocusMessageInputField: []string{"Alt+Down"},
|
||||
|
||||
SelectPreviousMessage: []string{"Up"},
|
||||
SelectNextMessage: []string{"Down"},
|
||||
SelectFirstMessage: []string{"Home"},
|
||||
SelectLastMessage: []string{"End"},
|
||||
ReplySelectedMessage: []string{"Rune[r]"},
|
||||
MentionReplySelectedMessage: []string{"Rune[R]"},
|
||||
CopySelectedMessage: []string{"Rune[c]"},
|
||||
SelectMessageReference: []string{"Rune[m]"},
|
||||
}
|
||||
37
discord.go
37
discord.go
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/ayntgl/discordgo"
|
||||
"github.com/ayntgl/discordo/config"
|
||||
"github.com/gen2brain/beeep"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
|
@ -19,26 +20,6 @@ var (
|
|||
strikeThroughRegex = regexp.MustCompile(`(?m)~~(.*?)~~`)
|
||||
)
|
||||
|
||||
func newSession() *discordgo.Session {
|
||||
s, err := discordgo.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s.UserAgent = conf.UserAgent
|
||||
s.Identify.Compress = false
|
||||
s.Identify.Intents = 0
|
||||
s.Identify.LargeThreshold = 0
|
||||
s.Identify.Properties.Device = ""
|
||||
s.Identify.Properties.Browser = "Chrome"
|
||||
s.Identify.Properties.OS = "Linux"
|
||||
|
||||
s.AddHandlerOnce(onSessionReady)
|
||||
s.AddHandler(onSessionMessageCreate)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) {
|
||||
dmNode := tview.NewTreeNode("Direct Messages").
|
||||
Collapse()
|
||||
|
|
@ -74,15 +55,15 @@ func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) {
|
|||
|
||||
func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
if selectedChannel == nil || selectedChannel.ID != m.ChannelID {
|
||||
if conf.Notifications {
|
||||
if config.General.Notifications {
|
||||
for _, u := range m.Mentions {
|
||||
if u.ID == session.State.User.ID {
|
||||
g, err := session.State.Guild(m.GuildID)
|
||||
if u.ID == app.Session.State.User.ID {
|
||||
g, err := app.Session.State.Guild(m.GuildID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c, err := session.State.Channel(m.ChannelID)
|
||||
c, err := app.Session.State.Channel(m.ChannelID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -114,7 +95,7 @@ func login(email, password string) (*loginResponse, error) {
|
|||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}{email, password}
|
||||
resp, err := session.RequestWithBucketID(
|
||||
resp, err := app.Session.RequestWithBucketID(
|
||||
"POST",
|
||||
discordgo.EndpointLogin,
|
||||
data,
|
||||
|
|
@ -139,7 +120,7 @@ func totp(code, ticket string) (*loginResponse, error) {
|
|||
Ticket string `json:"ticket"`
|
||||
}{code, ticket}
|
||||
e := discordgo.EndpointAuth + "mfa/totp"
|
||||
resp, err := session.RequestWithBucketID("POST", e, data, e)
|
||||
resp, err := app.Session.RequestWithBucketID("POST", e, data, e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -314,7 +295,7 @@ func buildAttachments(b *strings.Builder, as []*discordgo.MessageAttachment) {
|
|||
func buildMentions(content string, mentions []*discordgo.User) string {
|
||||
for _, mUser := range mentions {
|
||||
var color string
|
||||
if mUser.ID == session.State.User.ID {
|
||||
if mUser.ID == app.Session.State.User.ID {
|
||||
color = "[:#5865F2]"
|
||||
} else {
|
||||
color = "[#EB459E]"
|
||||
|
|
@ -334,7 +315,7 @@ func buildMentions(content string, mentions []*discordgo.User) string {
|
|||
}
|
||||
|
||||
func buildAuthor(b *strings.Builder, u *discordgo.User) {
|
||||
if u.ID == session.State.User.ID {
|
||||
if u.ID == app.Session.State.User.ID {
|
||||
b.WriteString("[#57F287]")
|
||||
} else {
|
||||
b.WriteString("[#ED4245]")
|
||||
|
|
|
|||
99
main.go
99
main.go
|
|
@ -1,9 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ayntgl/discordgo"
|
||||
"github.com/ayntgl/discordo/config"
|
||||
"github.com/ayntgl/discordo/ui"
|
||||
"github.com/ayntgl/discordo/util"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/zalando/go-keyring"
|
||||
|
|
@ -12,63 +14,49 @@ import (
|
|||
const service = "discordo"
|
||||
|
||||
var (
|
||||
app *tview.Application
|
||||
app *ui.App
|
||||
loginForm *tview.Form
|
||||
channelsTreeView *tview.TreeView
|
||||
messagesTextView *tview.TextView
|
||||
messageInputField *tview.InputField
|
||||
mainFlex *tview.Flex
|
||||
|
||||
conf *util.Config
|
||||
session *discordgo.Session
|
||||
|
||||
selectedChannel *discordgo.Channel
|
||||
selectedMessage int = -1
|
||||
)
|
||||
|
||||
func main() {
|
||||
conf = util.LoadConfig()
|
||||
|
||||
tview.Borders.Horizontal = conf.Borders.Horizontal
|
||||
tview.Borders.Vertical = conf.Borders.Vertical
|
||||
tview.Borders.TopLeft = conf.Borders.TopLeft
|
||||
tview.Borders.TopRight = conf.Borders.TopRight
|
||||
tview.Borders.BottomLeft = conf.Borders.BottomLeft
|
||||
tview.Borders.BottomRight = conf.Borders.BottomRight
|
||||
tview.Borders.HorizontalFocus = conf.Borders.HorizontalFocus
|
||||
tview.Borders.VerticalFocus = conf.Borders.VerticalFocus
|
||||
tview.Borders.TopLeftFocus = conf.Borders.TopLeftFocus
|
||||
tview.Borders.TopRightFocus = conf.Borders.TopRightFocus
|
||||
tview.Borders.BottomLeftFocus = conf.Borders.BottomLeftFocus
|
||||
tview.Borders.BottomRightFocus = conf.Borders.BottomRightFocus
|
||||
|
||||
tview.Styles.PrimitiveBackgroundColor = tcell.GetColor(conf.Theme.Background)
|
||||
tview.Styles.ContrastBackgroundColor = tcell.GetColor(conf.Theme.Background)
|
||||
tview.Styles.MoreContrastBackgroundColor = tcell.GetColor(conf.Theme.Background)
|
||||
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)
|
||||
tview.Styles.SecondaryTextColor = tcell.GetColor(conf.Theme.Text)
|
||||
tview.Styles.TertiaryTextColor = tcell.GetColor(conf.Theme.Text)
|
||||
tview.Styles.InverseTextColor = tcell.GetColor(conf.Theme.Text)
|
||||
tview.Styles.ContrastSecondaryTextColor = tcell.GetColor(conf.Theme.Text)
|
||||
|
||||
app = tview.NewApplication()
|
||||
app = ui.NewApp()
|
||||
app.
|
||||
EnableMouse(conf.Mouse).
|
||||
EnableMouse(config.General.Mouse).
|
||||
SetInputCapture(onAppInputCapture)
|
||||
|
||||
channelsTreeView = ui.NewChannelsTreeView()
|
||||
channelsTreeView.SetSelectedFunc(onChannelsTreeSelected)
|
||||
app.ChannelsTreeView.
|
||||
SetTopLevel(1).
|
||||
SetRoot(tview.NewTreeNode("")).
|
||||
SetSelectedFunc(onChannelsTreeSelected).
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
messagesTextView = ui.NewMessagesTextView()
|
||||
messagesTextView.
|
||||
app.MessagesTextView.
|
||||
SetRegions(true).
|
||||
SetDynamicColors(true).
|
||||
SetWordWrap(true).
|
||||
SetChangedFunc(func() { app.Draw() }).
|
||||
SetInputCapture(onMessagesViewInputCapture)
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetInputCapture(onMessagesViewInputCapture).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
messageInputField = ui.NewMessageInputField()
|
||||
messageInputField.SetInputCapture(onMessageInputFieldInputCapture)
|
||||
app.MessageInputField.
|
||||
SetPlaceholder("Message...").
|
||||
SetPlaceholderTextColor(tcell.ColorWhite).
|
||||
SetFieldBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
|
||||
SetInputCapture(onMessageInputFieldInputCapture).
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
rightFlex := tview.NewFlex().
|
||||
SetDirection(tview.FlexRow).
|
||||
|
|
@ -78,9 +66,9 @@ func main() {
|
|||
AddItem(channelsTreeView, 0, 1, false).
|
||||
AddItem(rightFlex, 0, 4, false)
|
||||
|
||||
token, err := keyring.Get(service, "token")
|
||||
if err != nil {
|
||||
token = conf.Token
|
||||
token := os.Getenv("DISCORDO_TOKEN")
|
||||
if token == "" {
|
||||
token, _ = keyring.Get(service, "token")
|
||||
}
|
||||
|
||||
if token != "" {
|
||||
|
|
@ -88,10 +76,10 @@ func main() {
|
|||
SetRoot(mainFlex, true).
|
||||
SetFocus(channelsTreeView)
|
||||
|
||||
session = newSession()
|
||||
session.Token = token
|
||||
session.Identify.Token = token
|
||||
if err := session.Open(); err != nil {
|
||||
app.Session.AddHandlerOnce(onSessionReady)
|
||||
app.Session.AddHandler(onSessionMessageCreate)
|
||||
err := app.Connect(token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -111,7 +99,6 @@ func onLoginFormLoginButtonSelected() {
|
|||
return
|
||||
}
|
||||
|
||||
session = newSession()
|
||||
// Login using the email and password
|
||||
lr, err := login(email, password)
|
||||
if err != nil {
|
||||
|
|
@ -123,9 +110,10 @@ func onLoginFormLoginButtonSelected() {
|
|||
SetRoot(mainFlex, true).
|
||||
SetFocus(channelsTreeView)
|
||||
|
||||
session.Token = lr.Token
|
||||
session.Identify.Token = lr.Token
|
||||
if err = session.Open(); err != nil {
|
||||
app.Session.AddHandlerOnce(onSessionReady)
|
||||
app.Session.AddHandler(onSessionMessageCreate)
|
||||
err = app.Connect(lr.Token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
|
@ -147,9 +135,10 @@ func onLoginFormLoginButtonSelected() {
|
|||
SetRoot(mainFlex, true).
|
||||
SetFocus(channelsTreeView)
|
||||
|
||||
session.Token = lr.Token
|
||||
session.Identify.Token = lr.Token
|
||||
if err = session.Open(); err != nil {
|
||||
app.Session.AddHandlerOnce(onSessionReady)
|
||||
app.Session.AddHandler(onSessionMessageCreate)
|
||||
err = app.Connect(lr.Token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
|
|
|||
47
ui.go
47
ui.go
|
|
@ -6,19 +6,20 @@ import (
|
|||
|
||||
"github.com/atotto/clipboard"
|
||||
"github.com/ayntgl/discordgo"
|
||||
"github.com/ayntgl/discordo/config"
|
||||
"github.com/ayntgl/discordo/util"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func onAppInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
||||
if util.HasKeybinding(conf.Keybindings.FocusChannelsTree, e.Name()) {
|
||||
if util.HasKeybinding(config.Keybindings.FocusChannelsTreeView, e.Name()) {
|
||||
app.SetFocus(channelsTreeView)
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.FocusMessagesView, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.FocusMessagesView, e.Name()) {
|
||||
app.SetFocus(messagesTextView)
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.FocusMessageInputField, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.FocusMessageInputField, e.Name()) {
|
||||
app.SetFocus(messageInputField)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -42,14 +43,14 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
|
|||
if len(n.GetChildren()) == 0 {
|
||||
// If the reference of the selected `*TreeNode` is `nil`, it is the direct messages `*TreeNode`.
|
||||
if id == nil {
|
||||
cs := session.State.PrivateChannels
|
||||
cs := app.Session.State.PrivateChannels
|
||||
sort.Slice(cs, func(i, j int) bool {
|
||||
return cs[i].LastMessageID > cs[j].LastMessageID
|
||||
})
|
||||
|
||||
for _, c := range cs {
|
||||
tag := "[::d]"
|
||||
if util.ChannelIsUnread(session.State, c) {
|
||||
if util.ChannelIsUnread(app.Session.State, c) {
|
||||
tag = "[::b]"
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
|
|||
n.AddChild(cn)
|
||||
}
|
||||
} else {
|
||||
g, err := session.State.Guild(id.(string))
|
||||
g, err := app.Session.State.Guild(id.(string))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -69,17 +70,17 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
|
|||
})
|
||||
|
||||
// Top-level channels
|
||||
createTopLevelChannelsNodes(channelsTreeView, session.State, n, g.Channels)
|
||||
createTopLevelChannelsNodes(channelsTreeView, app.Session.State, n, g.Channels)
|
||||
// Category channels
|
||||
createCategoryChannelsNodes(channelsTreeView, session.State, n, g.Channels)
|
||||
createCategoryChannelsNodes(channelsTreeView, app.Session.State, n, g.Channels)
|
||||
// Second-level channels
|
||||
createSecondLevelChannelsNodes(channelsTreeView, session.State, g.Channels)
|
||||
createSecondLevelChannelsNodes(channelsTreeView, app.Session.State, g.Channels)
|
||||
}
|
||||
}
|
||||
|
||||
n.SetExpanded(!n.IsExpanded())
|
||||
default: // Channels
|
||||
c, err := session.State.Channel(id.(string))
|
||||
c, err := app.Session.State.Channel(id.(string))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -104,7 +105,7 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
|
|||
}
|
||||
|
||||
go func() {
|
||||
ms, err := session.ChannelMessages(c.ID, conf.GetMessagesLimit, "", "", "")
|
||||
ms, err := app.Session.ChannelMessages(c.ID, config.General.FetchMessagesLimit, "", "", "")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -116,8 +117,8 @@ func onChannelsTreeSelected(n *tview.TreeNode) {
|
|||
// Scroll to the end of the text after the messages have been written to the TextView.
|
||||
messagesTextView.ScrollToEnd()
|
||||
|
||||
if len(ms) != 0 && util.ChannelIsUnread(session.State, c) {
|
||||
session.ChannelMessageAck(c.ID, c.LastMessageID, "")
|
||||
if len(ms) != 0 && util.ChannelIsUnread(app.Session.State, c) {
|
||||
app.Session.ChannelMessageAck(c.ID, c.LastMessageID, "")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -186,7 +187,7 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
if util.HasKeybinding(conf.Keybindings.SelectPreviousMessage, e.Name()) {
|
||||
if util.HasKeybinding(config.Keybindings.SelectPreviousMessage, e.Name()) {
|
||||
if len(messagesTextView.GetHighlights()) == 0 {
|
||||
selectedMessage = len(ms) - 1
|
||||
} else {
|
||||
|
|
@ -200,7 +201,7 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
Highlight(ms[selectedMessage].ID).
|
||||
ScrollToHighlight()
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.SelectNextMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.SelectNextMessage, e.Name()) {
|
||||
if len(messagesTextView.GetHighlights()) == 0 {
|
||||
selectedMessage = len(ms) - 1
|
||||
} else {
|
||||
|
|
@ -214,19 +215,19 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
Highlight(ms[selectedMessage].ID).
|
||||
ScrollToHighlight()
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.SelectFirstMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.SelectFirstMessage, e.Name()) {
|
||||
selectedMessage = 0
|
||||
messagesTextView.
|
||||
Highlight(ms[selectedMessage].ID).
|
||||
ScrollToHighlight()
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.SelectLastMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.SelectLastMessage, e.Name()) {
|
||||
selectedMessage = len(ms) - 1
|
||||
messagesTextView.
|
||||
Highlight(ms[selectedMessage].ID).
|
||||
ScrollToHighlight()
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.SelectMessageReference, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.SelectMessageReference, e.Name()) {
|
||||
hs := messagesTextView.GetHighlights()
|
||||
if len(hs) == 0 {
|
||||
return nil
|
||||
|
|
@ -241,7 +242,7 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.ReplySelectedMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.ReplySelectedMessage, e.Name()) {
|
||||
hs := messagesTextView.GetHighlights()
|
||||
if len(hs) == 0 {
|
||||
return nil
|
||||
|
|
@ -251,7 +252,7 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
messageInputField.SetTitle("Replying to " + m.Author.String())
|
||||
app.SetFocus(messageInputField)
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.MentionReplySelectedMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.MentionReplySelectedMessage, e.Name()) {
|
||||
hs := messagesTextView.GetHighlights()
|
||||
if len(hs) == 0 {
|
||||
return nil
|
||||
|
|
@ -261,7 +262,7 @@ func onMessagesViewInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
messageInputField.SetTitle("[@] Replying to " + m.Author.String())
|
||||
app.SetFocus(messageInputField)
|
||||
return nil
|
||||
} else if util.HasKeybinding(conf.Keybindings.CopySelectedMessage, e.Name()) {
|
||||
} else if util.HasKeybinding(config.Keybindings.CopySelectedMessage, e.Name()) {
|
||||
hs := messagesTextView.GetHighlights()
|
||||
if len(hs) == 0 {
|
||||
return nil
|
||||
|
|
@ -304,14 +305,14 @@ func onMessageInputFieldInputCapture(e *tcell.EventKey) *tcell.EventKey {
|
|||
d.AllowedMentions.RepliedUser = false
|
||||
}
|
||||
|
||||
go session.ChannelMessageSendComplex(m.ChannelID, d)
|
||||
go app.Session.ChannelMessageSendComplex(m.ChannelID, d)
|
||||
|
||||
selectedMessage = -1
|
||||
messagesTextView.Highlight()
|
||||
|
||||
messageInputField.SetTitle("")
|
||||
} else {
|
||||
go session.ChannelMessageSend(selectedChannel.ID, t)
|
||||
go app.Session.ChannelMessageSend(selectedChannel.ID, t)
|
||||
}
|
||||
|
||||
messageInputField.SetText("")
|
||||
|
|
|
|||
48
ui/app.go
Normal file
48
ui/app.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"github.com/ayntgl/discordgo"
|
||||
"github.com/ayntgl/discordo/config"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
*tview.Application
|
||||
|
||||
ChannelsTreeView *tview.TreeView
|
||||
MessagesTextView *tview.TextView
|
||||
MessageInputField *tview.InputField
|
||||
|
||||
Session *discordgo.Session
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
s, _ := discordgo.New()
|
||||
return &App{
|
||||
Application: tview.NewApplication(),
|
||||
|
||||
ChannelsTreeView: tview.NewTreeView(),
|
||||
MessagesTextView: tview.NewTextView(),
|
||||
MessageInputField: tview.NewInputField(),
|
||||
|
||||
Session: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (app *App) Connect(token string) error {
|
||||
app.Session.Token = token
|
||||
app.Session.UserAgent = config.General.UserAgent
|
||||
|
||||
app.Session.Identify.Token = token
|
||||
app.Session.Identify.Compress = false
|
||||
app.Session.Identify.Intents = 0
|
||||
app.Session.Identify.LargeThreshold = 0
|
||||
app.Session.Identify.Properties.Device = ""
|
||||
app.Session.Identify.Properties.Browser = "Firefox"
|
||||
app.Session.Identify.Properties.OS = "Linux"
|
||||
|
||||
// app.Session.AddHandlerOnce(onSessionReady)
|
||||
// app.Session.AddHandler(onSessionMessageCreate)
|
||||
|
||||
return app.Session.Open()
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package ui
|
||||
|
||||
import "github.com/rivo/tview"
|
||||
|
||||
func NewChannelsTreeView() *tview.TreeView {
|
||||
v := tview.NewTreeView()
|
||||
v.
|
||||
SetTopLevel(1).
|
||||
SetRoot(tview.NewTreeNode("")).
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
return v
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func NewMessageInputField() *tview.InputField {
|
||||
i := tview.NewInputField()
|
||||
i.
|
||||
SetPlaceholder("Message...").
|
||||
SetPlaceholderTextColor(tcell.ColorWhite).
|
||||
SetFieldBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
return i
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
package ui
|
||||
|
||||
import "github.com/rivo/tview"
|
||||
|
||||
func NewMessagesTextView() *tview.TextView {
|
||||
v := tview.NewTextView()
|
||||
v.
|
||||
SetRegions(true).
|
||||
SetDynamicColors(true).
|
||||
SetWordWrap(true).
|
||||
SetTitleAlign(tview.AlignLeft).
|
||||
SetBorder(true).
|
||||
SetBorderPadding(0, 0, 1, 0)
|
||||
|
||||
return v
|
||||
}
|
||||
139
util/config.go
139
util/config.go
|
|
@ -1,139 +0,0 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
const userAgent = "" +
|
||||
"Mozilla/5.0 (X11; Linux x86_64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/92.0.4515.131 Safari/537.36"
|
||||
|
||||
type keybindings struct {
|
||||
FocusChannelsTree []string `toml:"focus_channels_tree"`
|
||||
FocusMessagesView []string `toml:"focus_messages_view"`
|
||||
FocusMessageInputField []string `toml:"focus_message_input_field"`
|
||||
|
||||
SelectPreviousMessage []string `toml:"select_previous_message"`
|
||||
SelectNextMessage []string `toml:"select_next_message"`
|
||||
SelectFirstMessage []string `toml:"select_first_message"`
|
||||
SelectLastMessage []string `toml:"select_last_message"`
|
||||
SelectMessageReference []string `toml:"select_message_reference"`
|
||||
ReplySelectedMessage []string `toml:"reply_selected_message"`
|
||||
MentionReplySelectedMessage []string `toml:"mention_reply_selected_message"`
|
||||
CopySelectedMessage []string `toml:"copy_selected_message"`
|
||||
}
|
||||
|
||||
type theme struct {
|
||||
Background string `toml:"background"`
|
||||
|
||||
Border string `toml:"border"`
|
||||
Title string `toml:"title"`
|
||||
Graphics string `toml:"graphics"`
|
||||
Text string `toml:"text"`
|
||||
}
|
||||
|
||||
type borders struct {
|
||||
Horizontal rune
|
||||
Vertical rune
|
||||
TopLeft rune
|
||||
TopRight rune
|
||||
BottomLeft rune
|
||||
BottomRight rune
|
||||
|
||||
HorizontalFocus rune
|
||||
VerticalFocus rune
|
||||
TopLeftFocus rune
|
||||
TopRightFocus rune
|
||||
BottomLeftFocus rune
|
||||
BottomRightFocus rune
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Token string `toml:"token"`
|
||||
UserAgent string `toml:"user_agent"`
|
||||
Mouse bool `toml:"mouse"`
|
||||
Notifications bool `toml:"notifications"`
|
||||
GetMessagesLimit int `toml:"get_messages_limit"`
|
||||
|
||||
Theme theme `toml:"theme"`
|
||||
Keybindings keybindings `toml:"keybindings"`
|
||||
Borders borders `toml:"borders"`
|
||||
}
|
||||
|
||||
// LoadConfig loads the configuration file, if the configuration file exists or creates a new one if not, and returns it.
|
||||
func LoadConfig() *Config {
|
||||
configPath, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configPath += "/discordo.toml"
|
||||
|
||||
var c Config
|
||||
if _, err = os.Stat(configPath); os.IsNotExist(err) {
|
||||
f, err := os.Create(configPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
c = Config{
|
||||
Mouse: true,
|
||||
Notifications: true,
|
||||
UserAgent: userAgent,
|
||||
GetMessagesLimit: 50,
|
||||
Borders: borders{
|
||||
Horizontal: 0,
|
||||
Vertical: 0,
|
||||
TopLeft: 0,
|
||||
TopRight: 0,
|
||||
BottomLeft: 0,
|
||||
BottomRight: 0,
|
||||
|
||||
HorizontalFocus: tview.BoxDrawingsLightHorizontal,
|
||||
VerticalFocus: tview.BoxDrawingsLightVertical,
|
||||
TopLeftFocus: tview.BoxDrawingsLightDownAndRight,
|
||||
TopRightFocus: tview.BoxDrawingsLightDownAndLeft,
|
||||
BottomLeftFocus: tview.BoxDrawingsLightUpAndRight,
|
||||
BottomRightFocus: tview.BoxDrawingsLightUpAndLeft,
|
||||
},
|
||||
Theme: theme{
|
||||
Background: "black",
|
||||
|
||||
Border: "white",
|
||||
Title: "white",
|
||||
Graphics: "white",
|
||||
Text: "white",
|
||||
},
|
||||
Keybindings: keybindings{
|
||||
FocusChannelsTree: []string{"Alt+Left"},
|
||||
FocusMessagesView: []string{"Alt+Right"},
|
||||
FocusMessageInputField: []string{"Alt+Down"},
|
||||
|
||||
SelectPreviousMessage: []string{"Up"},
|
||||
SelectNextMessage: []string{"Down"},
|
||||
SelectFirstMessage: []string{"Home"},
|
||||
SelectLastMessage: []string{"End"},
|
||||
ReplySelectedMessage: []string{"Rune[r]"},
|
||||
MentionReplySelectedMessage: []string{"Rune[R]"},
|
||||
CopySelectedMessage: []string{"Rune[c]"},
|
||||
SelectMessageReference: []string{"Rune[m]"},
|
||||
},
|
||||
}
|
||||
err = toml.NewEncoder(f).Encode(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
_, err = toml.DecodeFile(configPath, &c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
return &c
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue