guilds_tree.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "sort"
  6. "github.com/diamondburned/arikawa/v3/discord"
  7. "github.com/rivo/tview"
  8. )
  9. type GuildsTree struct {
  10. *tview.TreeView
  11. root *tview.TreeNode
  12. }
  13. func newGuildsTree() *GuildsTree {
  14. gt := &GuildsTree{
  15. TreeView: tview.NewTreeView(),
  16. root: tview.NewTreeNode(""),
  17. }
  18. gt.SetGraphics(cfg.Theme.GuildsTree.Graphics)
  19. gt.SetRoot(gt.root)
  20. gt.SetTopLevel(1)
  21. gt.SetSelectedFunc(gt.onSelected)
  22. gt.SetBorder(cfg.Theme.GuildsTree.Border)
  23. gt.SetBorderPadding(cfg.BorderPadding())
  24. return gt
  25. }
  26. func (gt *GuildsTree) newGuildFromID(n *tview.TreeNode, gid discord.GuildID) error {
  27. g, err := discordState.Cabinet.Guild(gid)
  28. if err != nil {
  29. return err
  30. }
  31. gn := tview.NewTreeNode(g.Name)
  32. gn.SetReference(g.ID)
  33. n.AddChild(gn)
  34. return nil
  35. }
  36. func (gt *GuildsTree) newChannel(n *tview.TreeNode, c discord.Channel) {
  37. cn := tview.NewTreeNode(gt.channelToString(c))
  38. cn.SetReference(c.ID)
  39. n.AddChild(cn)
  40. }
  41. func (gt *GuildsTree) channelToString(c discord.Channel) string {
  42. switch c.Type {
  43. case discord.GuildText:
  44. return "#" + c.Name
  45. case discord.GuildVoice:
  46. return "v-" + c.Name
  47. case discord.GuildNews:
  48. return "n-" + c.Name
  49. case discord.GuildStore:
  50. return "s-" + c.Name
  51. default:
  52. return c.Name
  53. }
  54. }
  55. func (gt *GuildsTree) onSelected(n *tview.TreeNode) {
  56. if len(n.GetChildren()) != 0 {
  57. n.SetExpanded(!n.IsExpanded())
  58. return
  59. }
  60. switch ref := n.GetReference().(type) {
  61. case discord.GuildID:
  62. cs, err := discordState.Cabinet.Channels(ref)
  63. if err != nil {
  64. log.Println(err)
  65. return
  66. }
  67. sort.Slice(cs, func(i, j int) bool {
  68. return cs[i].Position < cs[j].Position
  69. })
  70. // Orphan (top-level) channels
  71. for _, c := range cs {
  72. if c.Type != discord.GuildCategory && !c.ParentID.IsValid() {
  73. gt.newChannel(n, c)
  74. }
  75. }
  76. // Category channels
  77. CATEGORY:
  78. for _, c := range cs {
  79. if c.Type == discord.GuildCategory {
  80. for _, nestedChannel := range cs {
  81. if nestedChannel.ParentID == c.ID {
  82. gt.newChannel(n, c)
  83. continue CATEGORY
  84. }
  85. }
  86. gt.newChannel(n, c)
  87. }
  88. }
  89. // Children (category-bound) channels
  90. for _, c := range cs {
  91. if c.Type != discord.GuildCategory && c.ParentID.IsValid() {
  92. var parent *tview.TreeNode
  93. n.Walk(func(node, _ *tview.TreeNode) bool {
  94. if node.GetReference() == c.ParentID {
  95. parent = node
  96. return false
  97. }
  98. return true
  99. })
  100. if parent != nil {
  101. gt.newChannel(parent, c)
  102. }
  103. }
  104. }
  105. case discord.ChannelID:
  106. messagesText.Clear()
  107. c, err := discordState.Cabinet.Channel(ref)
  108. if err != nil {
  109. log.Println(err)
  110. return
  111. }
  112. ms, err := discordState.Messages(ref, cfg.MessagesLimit)
  113. if err != nil {
  114. log.Println(err)
  115. return
  116. }
  117. for i := len(ms) - 1; i >= 0; i-- {
  118. if messagesText.newMessage(&ms[i]); err != nil {
  119. fmt.Println(err)
  120. continue
  121. }
  122. }
  123. messagesText.SetTitle(gt.channelToString(*c))
  124. app.SetFocus(messagesText)
  125. }
  126. }