guilds_tree.go 2.6 KB

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