util.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package main
  2. import (
  3. "sort"
  4. "strings"
  5. "github.com/ayntgl/discordgo"
  6. "github.com/rivo/tview"
  7. )
  8. func generateChannelRepr(c *discordgo.Channel) string {
  9. var repr string
  10. if c.Name != "" {
  11. repr = "#" + c.Name
  12. } else if len(c.Recipients) == 1 {
  13. rp := c.Recipients[0]
  14. repr = rp.Username + "#" + rp.Discriminator
  15. } else {
  16. rps := make([]string, len(c.Recipients))
  17. for i, r := range c.Recipients {
  18. rps[i] = r.Username + "#" + r.Discriminator
  19. }
  20. repr = strings.Join(rps, ", ")
  21. }
  22. return repr
  23. }
  24. func findByMessageID(mID string) *discordgo.Message {
  25. for _, m := range selectedChannel.Messages {
  26. if m.ID == mID {
  27. return m
  28. }
  29. }
  30. return nil
  31. }
  32. func createPrivateChannels(n *tview.TreeNode) {
  33. cs := session.State.PrivateChannels
  34. sort.Slice(cs, func(i, j int) bool {
  35. return cs[i].LastMessageID > cs[j].LastMessageID
  36. })
  37. for _, c := range cs {
  38. var tag string
  39. if isUnread(c) {
  40. tag = "[::b]"
  41. } else {
  42. tag = "[::d]"
  43. }
  44. cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
  45. SetReference(c.ID)
  46. n.AddChild(cn)
  47. }
  48. }
  49. func createGuilds(n *tview.TreeNode) {
  50. gs := session.State.Guilds
  51. sort.Slice(gs, func(a, b int) bool {
  52. found := false
  53. for _, gID := range session.State.Settings.GuildPositions {
  54. if found {
  55. if gID == gs[b].ID {
  56. return true
  57. }
  58. } else {
  59. if gID == gs[a].ID {
  60. found = true
  61. }
  62. }
  63. }
  64. return false
  65. })
  66. for _, g := range gs {
  67. gn := tview.NewTreeNode(g.Name).Collapse()
  68. n.AddChild(gn)
  69. cs := g.Channels
  70. sort.Slice(cs, func(i, j int) bool {
  71. return cs[i].Position < cs[j].Position
  72. })
  73. // Top-level channels
  74. createTopLevelChannelsTreeNodes(gn, cs)
  75. // Category channels
  76. createCategoryChannelsTreeNodes(gn, cs)
  77. // Second-level channels
  78. createSecondLevelChannelsTreeNodes(cs)
  79. }
  80. }
  81. func createTopLevelChannelsTreeNodes(
  82. n *tview.TreeNode,
  83. cs []*discordgo.Channel,
  84. ) {
  85. for _, c := range cs {
  86. if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) &&
  87. (c.ParentID == "") {
  88. p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
  89. if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
  90. continue
  91. }
  92. var tag string
  93. if isUnread(c) {
  94. tag = "[::b]"
  95. } else {
  96. tag = "[::d]"
  97. }
  98. cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
  99. SetReference(c.ID)
  100. n.AddChild(cn)
  101. continue
  102. }
  103. }
  104. }
  105. func createCategoryChannelsTreeNodes(
  106. n *tview.TreeNode,
  107. cs []*discordgo.Channel,
  108. ) {
  109. CategoryLoop:
  110. for _, c := range cs {
  111. if c.Type == discordgo.ChannelTypeGuildCategory {
  112. p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
  113. if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
  114. continue
  115. }
  116. for _, child := range cs {
  117. if child.ParentID == c.ID {
  118. cn := tview.NewTreeNode(c.Name).
  119. SetReference(c.ID)
  120. n.AddChild(cn)
  121. continue CategoryLoop
  122. }
  123. }
  124. cn := tview.NewTreeNode(c.Name).
  125. SetReference(c.ID)
  126. n.AddChild(cn)
  127. }
  128. }
  129. }
  130. func createSecondLevelChannelsTreeNodes(cs []*discordgo.Channel) {
  131. for _, c := range cs {
  132. if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) &&
  133. (c.ParentID != "") {
  134. p, err := session.State.UserChannelPermissions(session.State.User.ID, c.ID)
  135. if err != nil || p&discordgo.PermissionViewChannel != discordgo.PermissionViewChannel {
  136. continue
  137. }
  138. var tag string
  139. if isUnread(c) {
  140. tag = "[::b]"
  141. } else {
  142. tag = "[::d]"
  143. }
  144. pn := getTreeNodeByReference(c.ParentID)
  145. if pn != nil {
  146. cn := tview.NewTreeNode(tag + generateChannelRepr(c) + "[::-]").
  147. SetReference(c.ID)
  148. pn.AddChild(cn)
  149. }
  150. }
  151. }
  152. }
  153. func getTreeNodeByReference(r interface{}) (mn *tview.TreeNode) {
  154. channelsTree.GetRoot().Walk(func(n, _ *tview.TreeNode) bool {
  155. if n.GetReference() == r {
  156. mn = n
  157. return false
  158. }
  159. return true
  160. })
  161. return
  162. }
  163. func isUnread(c *discordgo.Channel) bool {
  164. if c.LastMessageID == "" {
  165. return false
  166. }
  167. for _, rs := range session.State.ReadState {
  168. if c.ID == rs.ID {
  169. return c.LastMessageID != rs.LastMessageID
  170. }
  171. }
  172. return false
  173. }