This commit is contained in:
ayn2op 2022-12-30 20:05:26 +05:30
parent f96e4a5f0d
commit 7111df5c82
9 changed files with 169 additions and 66 deletions

View file

@ -1,18 +0,0 @@
package main
import "github.com/rivo/tview"
type ChannelsTree struct {
*tview.TreeView
}
func newChannelsTree() *ChannelsTree {
ct := &ChannelsTree{
TreeView: tview.NewTreeView(),
}
ct.SetBorder(true)
ct.SetBorderPadding(cfg.BorderPadding())
return ct
}

View file

@ -13,13 +13,9 @@ type ThemeConfig struct {
}
type Config struct {
Mouse bool
Theme ThemeConfig
}
func (c *Config) BorderPadding() (int, int, int, int) {
pad := c.Theme.BorderPadding
return pad[0], pad[1], pad[2], pad[3]
Mouse bool
MessagesLimit uint
Theme ThemeConfig
}
func newConfig() (*Config, error) {
@ -34,7 +30,9 @@ func newConfig() (*Config, error) {
}
c := Config{
Mouse: true,
Mouse: true,
MessagesLimit: 50,
Theme: ThemeConfig{
BorderPadding: [...]int{1, 1, 1, 1},
},
@ -66,3 +64,8 @@ func newConfig() (*Config, error) {
return &c, nil
}
func (c *Config) BorderPadding() (int, int, int, int) {
pad := c.Theme.BorderPadding
return pad[0], pad[1], pad[2], pad[3]
}

16
go.mod
View file

@ -4,20 +4,20 @@ go 1.19
require (
github.com/diamondburned/arikawa/v3 v3.1.0
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c
)
require (
github.com/gdamore/encoding v1.0.0 // indirect
github.com/gdamore/tcell/v2 v2.5.3 // indirect
github.com/gorilla/schema v1.2.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
github.com/rivo/uniseg v0.4.3 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/term v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/time v0.3.0 // indirect
)

27
go.sum
View file

@ -6,34 +6,39 @@ github.com/gdamore/tcell/v2 v2.5.3 h1:b9XQrT6QGbgI7JvZOJXFNczOQeIYbo8BfeSMzt2sAV
github.com/gdamore/tcell/v2 v2.5.3/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tvaKJ6uGBo=
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c h1:Y4GSXEYKYAtguH10lmQmYb7hRkJ7U+m8GvnFHKU2jrk=
github.com/rivo/tview v0.0.0-20221221172820-02e38ea9604c/go.mod h1:lBUy/T5kyMudFzWUH/C2moN+NlU5qF505vzOyINXuUQ=
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c h1:Xa0IDAwI/b4D3AQwFOhvOeYB/H0N8Bhhe3XJWSa2vjg=
github.com/rivo/tview v0.0.0-20221229180733-b86a50a5126c/go.mod h1:lBUy/T5kyMudFzWUH/C2moN+NlU5qF505vzOyINXuUQ=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211001092434-39dca1131b70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 h1:saXMvIOKvRFwbOMicHXr0B1uwoxq9dGmLe5ExMES6c4=
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View file

@ -1,31 +1,37 @@
package main
import (
"log"
"github.com/diamondburned/arikawa/v3/discord"
"github.com/rivo/tview"
)
type GuildsTree struct {
*tview.TreeView
root *tview.TreeNode
}
func newGuildsTree() *GuildsTree {
gt := &GuildsTree{
TreeView: tview.NewTreeView(),
root: tview.NewTreeNode(""),
}
root := tview.NewTreeNode("")
gt.SetRoot(root)
gt.SetRoot(gt.root)
gt.SetTopLevel(1)
gt.SetSelectedFunc(gt.onSelected)
gt.SetTitle("Guilds")
gt.SetBorder(true)
gt.SetBorderPadding(cfg.BorderPadding())
return gt
}
func (gt *GuildsTree) newGuild(n *tview.TreeNode, gid discord.GuildID) error {
func (gt *GuildsTree) newGuildFromID(n *tview.TreeNode, gid discord.GuildID) error {
g, err := discordState.Cabinet.Guild(gid)
if err != nil {
return err
@ -37,9 +43,100 @@ func (gt *GuildsTree) newGuild(n *tview.TreeNode, gid discord.GuildID) error {
return nil
}
func (gt *GuildsTree) onSelected(n *tview.TreeNode) {
ref := n.GetReference()
if ref == nil {
func (gt *GuildsTree) newChannel(n *tview.TreeNode, c discord.Channel) {
cn := tview.NewTreeNode(gt.channelToString(c))
cn.SetReference(c.ID)
n.AddChild(cn)
}
func (gt *GuildsTree) channelToString(c discord.Channel) string {
switch c.Type {
case discord.GuildText:
return "#" + c.Name
case discord.GuildVoice:
return "v-" + c.Name
case discord.GuildNews:
return "n-" + c.Name
case discord.GuildStore:
return "s-" + c.Name
default:
return c.Name
}
}
func (gt *GuildsTree) onSelected(n *tview.TreeNode) {
if len(n.GetChildren()) != 0 {
n.SetExpanded(!n.IsExpanded())
}
switch ref := n.GetReference().(type) {
case discord.GuildID:
cs, err := discordState.Cabinet.Channels(ref)
if err != nil {
log.Println(err)
return
}
// Orphan (top-level) channels
for _, c := range cs {
if c.Type != discord.GuildCategory && !c.ParentID.IsValid() {
gt.newChannel(n, c)
}
}
// Category channels
CATEGORY:
for _, c := range cs {
if c.Type == discord.GuildCategory {
for _, nestedChannel := range cs {
if nestedChannel.ParentID == c.ID {
gt.newChannel(n, c)
continue CATEGORY
}
}
gt.newChannel(n, c)
}
}
// Children (category-bound) channels
for _, c := range cs {
if c.ParentID.IsValid() {
var parent *tview.TreeNode
n.Walk(func(node, _ *tview.TreeNode) bool {
if node.GetReference() == c.ParentID {
parent = node
return false
}
return true
})
if parent != nil {
gt.newChannel(parent, c)
}
}
}
case discord.ChannelID:
messagesText.Clear()
c, err := discordState.Cabinet.Channel(ref)
if err != nil {
log.Println(err)
return
}
ms, err := discordState.Messages(ref, cfg.MessagesLimit)
if err != nil {
log.Println(err)
return
}
for _, m := range ms {
messagesText.newMessage(&m)
}
messagesText.SetTitle(gt.channelToString(*c))
app.SetFocus(messagesText)
}
}

View file

@ -17,7 +17,6 @@ var (
app *tview.Application
flex *tview.Flex
guildsTree *GuildsTree
channelsTree *ChannelsTree
messagesText *MessagesText
messageInput *MessageInput
)
@ -39,7 +38,6 @@ func main() {
app = tview.NewApplication()
guildsTree = newGuildsTree()
channelsTree = newChannelsTree()
messagesText = newMessagesText()
messageInput = newMessageInput()
@ -48,18 +46,13 @@ func main() {
log.Fatal(err)
}
left := tview.NewFlex()
left.SetDirection(tview.FlexRow)
left.AddItem(guildsTree, 0, 1, true)
left.AddItem(channelsTree, 0, 1, false)
right := tview.NewFlex()
right.SetDirection(tview.FlexRow)
right.AddItem(messagesText, 0, 1, false)
right.AddItem(messageInput, 3, 1, false)
flex = tview.NewFlex()
flex.AddItem(left, 0, 1, false)
flex.AddItem(guildsTree, 0, 1, false)
flex.AddItem(right, 0, 4, false)
app.EnableMouse(cfg.Mouse)

View file

@ -1,11 +1,17 @@
package main
import (
"fmt"
"strings"
"github.com/diamondburned/arikawa/v3/discord"
"github.com/rivo/tview"
)
type MessagesText struct {
*tview.TextView
builder strings.Builder
}
func newMessagesText() *MessagesText {
@ -21,3 +27,19 @@ func newMessagesText() *MessagesText {
return mt
}
func (mt *MessagesText) newMessage(m *discord.Message) {
switch m.Type {
case discord.DefaultMessage:
{
mt.builder.WriteString("[blue::b]")
mt.builder.WriteString(m.Author.Username)
mt.builder.WriteString("[-:-:-]")
}
mt.builder.WriteByte('\n')
mt.builder.WriteByte('\n')
}
fmt.Fprintln(mt, mt.builder.String())
}

3
out.log Normal file
View file

@ -0,0 +1,3 @@
2022/12/30 20:03:24 Discord 403 error: Missing Access
2022/12/30 20:03:44 Discord 403 error: Missing Access
2022/12/30 20:03:58 Discord 403 error: Missing Access

View file

@ -23,24 +23,22 @@ func newState(token string) *State {
}
func (s *State) onReady(r *gateway.ReadyEvent) {
root := guildsTree.GetRoot()
dmNode := tview.NewTreeNode("Direct Messages")
root.AddChild(dmNode)
guildsTree.root.AddChild(dmNode)
for _, gf := range r.UserSettings.GuildFolders {
/// If the ID of the guild folder is zero, the guild folder only contains single guild.
if gf.ID == 0 {
if err := guildsTree.newGuild(root, gf.GuildIDs[0]); err != nil {
if err := guildsTree.newGuildFromID(guildsTree.root, gf.GuildIDs[0]); err != nil {
log.Println(err)
continue
}
} else {
gfNode := tview.NewTreeNode("Folder")
root.AddChild(gfNode)
guildsTree.root.AddChild(gfNode)
for _, gid := range gf.GuildIDs {
if err := guildsTree.newGuild(gfNode, gid); err != nil {
if err := guildsTree.newGuildFromID(gfNode, gid); err != nil {
log.Println(err)
continue
}
@ -48,6 +46,6 @@ func (s *State) onReady(r *gateway.ReadyEvent) {
}
}
guildsTree.SetCurrentNode(root)
guildsTree.SetCurrentNode(guildsTree.root)
app.SetFocus(guildsTree)
}