state.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // Discordgo - Discord bindings for Go
  2. // Available at https://github.com/bwmarrin/discordgo
  3. // Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
  4. // Use of this source code is governed by a BSD-style
  5. // license that can be found in the LICENSE file.
  6. // This file contains code related to state tracking. If enabled, state
  7. // tracking will capture the initial READY packet and many other websocket
  8. // events and maintain an in-memory state of of guilds, channels, users, and
  9. // so forth. This information can be accessed through the Session.State struct.
  10. package discordgo
  11. import "errors"
  12. var nilError error = errors.New("State not instantiated, please use discordgo.New() or assign Session.State.")
  13. // NewState creates an empty state.
  14. func NewState() *State {
  15. return &State{
  16. Ready: Ready{
  17. PrivateChannels: []Channel{},
  18. Guilds: []Guild{},
  19. },
  20. }
  21. }
  22. // OnReady takes a Ready event and updates all internal state.
  23. func (s *State) OnReady(r *Ready) error {
  24. if s == nil {
  25. return nilError
  26. }
  27. s.Ready = *r
  28. return nil
  29. }
  30. // GuildAdd adds a guild to the current world state, or
  31. // updates it if it already exists.
  32. func (s *State) GuildAdd(guild *Guild) error {
  33. if s == nil {
  34. return nilError
  35. }
  36. for _, g := range s.Guilds {
  37. if g.ID == guild.ID {
  38. // This could be a little faster ;)
  39. for _, m := range guild.Members {
  40. s.MemberAdd(&m)
  41. }
  42. for _, c := range guild.Channels {
  43. s.ChannelAdd(&c)
  44. }
  45. return nil
  46. }
  47. }
  48. s.Guilds = append(s.Guilds, *guild)
  49. return nil
  50. }
  51. // GuildRemove removes a guild from current world state.
  52. func (s *State) GuildRemove(guild *Guild) error {
  53. if s == nil {
  54. return nilError
  55. }
  56. for i, g := range s.Guilds {
  57. if g.ID == guild.ID {
  58. s.Guilds = append(s.Guilds[:i], s.Guilds[i+1:]...)
  59. return nil
  60. }
  61. }
  62. return errors.New("Guild not found.")
  63. }
  64. // Guild gets a guild by ID.
  65. // Useful for querying if @me is in a guild:
  66. // _, err := discordgo.Session.State.Guild(guildID)
  67. // isInGuild := err == nil
  68. func (s *State) Guild(guildID string) (*Guild, error) {
  69. if s == nil {
  70. return nil, nilError
  71. }
  72. for _, g := range s.Guilds {
  73. if g.ID == guildID {
  74. return &g, nil
  75. }
  76. }
  77. return nil, errors.New("Guild not found.")
  78. }
  79. // TODO: Consider moving Guild state update methods onto *Guild.
  80. // MemberAdd adds a member to the current world state, or
  81. // updates it if it already exists.
  82. func (s *State) MemberAdd(member *Member) error {
  83. if s == nil {
  84. return nilError
  85. }
  86. guild, err := s.Guild(member.GuildID)
  87. if err != nil {
  88. return err
  89. }
  90. for i, m := range guild.Members {
  91. if m.User.ID == member.User.ID {
  92. guild.Members[i] = *member
  93. return nil
  94. }
  95. }
  96. guild.Members = append(guild.Members, *member)
  97. return nil
  98. }
  99. // MemberRemove removes a member from current world state.
  100. func (s *State) MemberRemove(member *Member) error {
  101. if s == nil {
  102. return nilError
  103. }
  104. guild, err := s.Guild(member.GuildID)
  105. if err != nil {
  106. return err
  107. }
  108. for i, m := range guild.Members {
  109. if m.User.ID == member.User.ID {
  110. guild.Members = append(guild.Members[:i], guild.Members[i+1:]...)
  111. return nil
  112. }
  113. }
  114. return errors.New("Member not found.")
  115. }
  116. // Member gets a member by ID from a guild.
  117. func (s *State) Member(guildID, userID string) (*Member, error) {
  118. if s == nil {
  119. return nil, nilError
  120. }
  121. guild, err := s.Guild(guildID)
  122. if err != nil {
  123. return nil, err
  124. }
  125. for _, m := range guild.Members {
  126. if m.User.ID == userID {
  127. return &m, nil
  128. }
  129. }
  130. return nil, errors.New("Member not found.")
  131. }
  132. // ChannelAdd adds a guild to the current world state, or
  133. // updates it if it already exists.
  134. // Channels may exist either as PrivateChannels or inside
  135. // a guild.
  136. func (s *State) ChannelAdd(channel *Channel) error {
  137. if s == nil {
  138. return nilError
  139. }
  140. if channel.IsPrivate {
  141. for i, c := range s.PrivateChannels {
  142. if c.ID == channel.ID {
  143. s.PrivateChannels[i] = *channel
  144. return nil
  145. }
  146. }
  147. s.PrivateChannels = append(s.PrivateChannels, *channel)
  148. } else {
  149. guild, err := s.Guild(channel.GuildID)
  150. if err != nil {
  151. return err
  152. }
  153. for i, c := range guild.Channels {
  154. if c.ID == channel.ID {
  155. guild.Channels[i] = *channel
  156. return nil
  157. }
  158. }
  159. guild.Channels = append(guild.Channels, *channel)
  160. }
  161. return nil
  162. }
  163. // ChannelRemove removes a channel from current world state.
  164. func (s *State) ChannelRemove(channel *Channel) error {
  165. if s == nil {
  166. return nilError
  167. }
  168. if channel.IsPrivate {
  169. for i, c := range s.PrivateChannels {
  170. if c.ID == channel.ID {
  171. s.PrivateChannels = append(s.PrivateChannels[:i], s.PrivateChannels[i+1:]...)
  172. return nil
  173. }
  174. }
  175. } else {
  176. guild, err := s.Guild(channel.GuildID)
  177. if err != nil {
  178. return err
  179. }
  180. for i, c := range guild.Channels {
  181. if c.ID == channel.ID {
  182. guild.Channels = append(guild.Channels[:i], guild.Channels[i+1:]...)
  183. return nil
  184. }
  185. }
  186. }
  187. return errors.New("Channel not found.")
  188. }
  189. // GuildChannel gets a channel by ID from a guild.
  190. func (s *State) GuildChannel(guildID, channelID string) (*Channel, error) {
  191. if s == nil {
  192. return nil, nilError
  193. }
  194. guild, err := s.Guild(guildID)
  195. if err != nil {
  196. return nil, err
  197. }
  198. for _, c := range guild.Channels {
  199. if c.ID == channelID {
  200. return &c, nil
  201. }
  202. }
  203. return nil, errors.New("Channel not found.")
  204. }
  205. // PrivateChannel gets a private channel by ID.
  206. func (s *State) PrivateChannel(channelID string) (*Channel, error) {
  207. if s == nil {
  208. return nil, nilError
  209. }
  210. for _, c := range s.PrivateChannels {
  211. if c.ID == channelID {
  212. return &c, nil
  213. }
  214. }
  215. return nil, errors.New("Channel not found.")
  216. }
  217. // Channel gets a channel by ID, it will look in all guilds an private channels.
  218. func (s *State) Channel(channelID string) (*Channel, error) {
  219. if s == nil {
  220. return nil, nilError
  221. }
  222. c, err := s.PrivateChannel(channelID)
  223. if err == nil {
  224. return c, nil
  225. }
  226. for _, g := range s.Guilds {
  227. c, err := s.GuildChannel(g.ID, channelID)
  228. if err == nil {
  229. return c, nil
  230. }
  231. }
  232. return nil, errors.New("Channel not found.")
  233. }
  234. // Emoji returns an emoji for a guild and emoji id.
  235. func (s *State) Emoji(guildID, emojiID string) (*Emoji, error) {
  236. if s == nil {
  237. return nil, nilError
  238. }
  239. guild, err := s.Guild(guildID)
  240. if err != nil {
  241. return nil, err
  242. }
  243. for _, e := range guild.Emojis {
  244. if e.ID == emojiID {
  245. return &e, nil
  246. }
  247. }
  248. return nil, errors.New("Emoji not found.")
  249. }
  250. // EmojiAdd adds an emoji to the current world state.
  251. func (s *State) EmojiAdd(guildID string, emoji *Emoji) error {
  252. if s == nil {
  253. return nilError
  254. }
  255. guild, err := s.Guild(guildID)
  256. if err != nil {
  257. return err
  258. }
  259. for i, e := range guild.Emojis {
  260. if e.ID == emoji.ID {
  261. guild.Emojis[i] = *emoji
  262. return nil
  263. }
  264. }
  265. guild.Emojis = append(guild.Emojis, *emoji)
  266. return nil
  267. }
  268. // EmojisAdd adds multiple emojis to the world state.
  269. func (s *State) EmojisAdd(guildID string, emojis []Emoji) error {
  270. for _, e := range emojis {
  271. if err := s.EmojiAdd(guildID, &e); err != nil {
  272. return err
  273. }
  274. }
  275. return nil
  276. }