ayn2op 3 ani în urmă
părinte
comite
7111df5c82
9 a modificat fișierele cu 168 adăugiri și 65 ștergeri
  1. 0 18
      channels_tree.go
  2. 11 8
      config.go
  3. 8 8
      go.mod
  4. 16 11
      go.sum
  5. 102 5
      guilds_tree.go
  6. 1 8
      main.go
  7. 22 0
      messages_text.go
  8. 3 0
      out.log
  9. 5 7
      state.go

+ 0 - 18
channels_tree.go

@@ -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
-}

+ 11 - 8
config.go

@@ -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]
+}

+ 8 - 8
go.mod

@@ -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
 )

+ 16 - 11
go.sum

@@ -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=

+ 102 - 5
guilds_tree.go

@@ -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) 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) {
-	ref := n.GetReference()
-	if ref == nil {
+	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)
 	}
 }

+ 1 - 8
main.go

@@ -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)

+ 22 - 0
messages_text.go

@@ -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 - 0
out.log

@@ -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

+ 5 - 7
state.go

@@ -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)
 }