state.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  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 (
  12. "errors"
  13. "sort"
  14. "sync"
  15. )
  16. // ErrNilState is returned when the state is nil.
  17. var ErrNilState = errors.New("state not instantiated, please use discordgo.New() or assign Session.State")
  18. // ErrStateNotFound is returned when the state cache
  19. // requested is not found
  20. var ErrStateNotFound = errors.New("state cache not found")
  21. // A State contains the current known state.
  22. // As discord sends this in a READY blob, it seems reasonable to simply
  23. // use that struct as the data store.
  24. type State struct {
  25. sync.RWMutex
  26. Ready
  27. // MaxMessageCount represents how many messages per channel the state will store.
  28. MaxMessageCount int
  29. TrackChannels bool
  30. TrackEmojis bool
  31. TrackMembers bool
  32. TrackRoles bool
  33. TrackVoice bool
  34. TrackPresences bool
  35. guildMap map[string]*Guild
  36. channelMap map[string]*Channel
  37. memberMap map[string]map[string]*Member
  38. }
  39. // NewState creates an empty state.
  40. func NewState() *State {
  41. return &State{
  42. Ready: Ready{
  43. PrivateChannels: []*Channel{},
  44. Guilds: []*Guild{},
  45. },
  46. TrackChannels: true,
  47. TrackEmojis: true,
  48. TrackMembers: true,
  49. TrackRoles: true,
  50. TrackVoice: true,
  51. TrackPresences: true,
  52. guildMap: make(map[string]*Guild),
  53. channelMap: make(map[string]*Channel),
  54. memberMap: make(map[string]map[string]*Member),
  55. }
  56. }
  57. func (s *State) createMemberMap(guild *Guild) {
  58. members := make(map[string]*Member)
  59. for _, m := range guild.Members {
  60. members[m.User.ID] = m
  61. }
  62. s.memberMap[guild.ID] = members
  63. }
  64. // GuildAdd adds a guild to the current world state, or
  65. // updates it if it already exists.
  66. func (s *State) GuildAdd(guild *Guild) error {
  67. if s == nil {
  68. return ErrNilState
  69. }
  70. s.Lock()
  71. defer s.Unlock()
  72. // Update the channels to point to the right guild, adding them to the channelMap as we go
  73. for _, c := range guild.Channels {
  74. s.channelMap[c.ID] = c
  75. }
  76. // If this guild contains a new member slice, we must regenerate the member map so the pointers stay valid
  77. if guild.Members != nil {
  78. s.createMemberMap(guild)
  79. } else if _, ok := s.memberMap[guild.ID]; !ok {
  80. // Even if we have no new member slice, we still initialize the member map for this guild if it doesn't exist
  81. s.memberMap[guild.ID] = make(map[string]*Member)
  82. }
  83. if g, ok := s.guildMap[guild.ID]; ok {
  84. // We are about to replace `g` in the state with `guild`, but first we need to
  85. // make sure we preserve any fields that the `guild` doesn't contain from `g`.
  86. if guild.Roles == nil {
  87. guild.Roles = g.Roles
  88. }
  89. if guild.Emojis == nil {
  90. guild.Emojis = g.Emojis
  91. }
  92. if guild.Members == nil {
  93. guild.Members = g.Members
  94. }
  95. if guild.Presences == nil {
  96. guild.Presences = g.Presences
  97. }
  98. if guild.Channels == nil {
  99. guild.Channels = g.Channels
  100. }
  101. if guild.VoiceStates == nil {
  102. guild.VoiceStates = g.VoiceStates
  103. }
  104. *g = *guild
  105. return nil
  106. }
  107. s.Guilds = append(s.Guilds, guild)
  108. s.guildMap[guild.ID] = guild
  109. return nil
  110. }
  111. // GuildRemove removes a guild from current world state.
  112. func (s *State) GuildRemove(guild *Guild) error {
  113. if s == nil {
  114. return ErrNilState
  115. }
  116. _, err := s.Guild(guild.ID)
  117. if err != nil {
  118. return err
  119. }
  120. s.Lock()
  121. defer s.Unlock()
  122. delete(s.guildMap, guild.ID)
  123. for i, g := range s.Guilds {
  124. if g.ID == guild.ID {
  125. s.Guilds = append(s.Guilds[:i], s.Guilds[i+1:]...)
  126. return nil
  127. }
  128. }
  129. return nil
  130. }
  131. // Guild gets a guild by ID.
  132. // Useful for querying if @me is in a guild:
  133. // _, err := discordgo.Session.State.Guild(guildID)
  134. // isInGuild := err == nil
  135. func (s *State) Guild(guildID string) (*Guild, error) {
  136. if s == nil {
  137. return nil, ErrNilState
  138. }
  139. s.RLock()
  140. defer s.RUnlock()
  141. if g, ok := s.guildMap[guildID]; ok {
  142. return g, nil
  143. }
  144. return nil, ErrStateNotFound
  145. }
  146. // PresenceAdd adds a presence to the current world state, or
  147. // updates it if it already exists.
  148. func (s *State) PresenceAdd(guildID string, presence *Presence) error {
  149. if s == nil {
  150. return ErrNilState
  151. }
  152. guild, err := s.Guild(guildID)
  153. if err != nil {
  154. return err
  155. }
  156. s.Lock()
  157. defer s.Unlock()
  158. for i, p := range guild.Presences {
  159. if p.User.ID == presence.User.ID {
  160. //guild.Presences[i] = presence
  161. //Update status
  162. guild.Presences[i].Game = presence.Game
  163. guild.Presences[i].Roles = presence.Roles
  164. if presence.Status != "" {
  165. guild.Presences[i].Status = presence.Status
  166. }
  167. if presence.Nick != "" {
  168. guild.Presences[i].Nick = presence.Nick
  169. }
  170. //Update the optionally sent user information
  171. //ID Is a mandatory field so you should not need to check if it is empty
  172. guild.Presences[i].User.ID = presence.User.ID
  173. if presence.User.Avatar != "" {
  174. guild.Presences[i].User.Avatar = presence.User.Avatar
  175. }
  176. if presence.User.Discriminator != "" {
  177. guild.Presences[i].User.Discriminator = presence.User.Discriminator
  178. }
  179. if presence.User.Email != "" {
  180. guild.Presences[i].User.Email = presence.User.Email
  181. }
  182. if presence.User.Token != "" {
  183. guild.Presences[i].User.Token = presence.User.Token
  184. }
  185. if presence.User.Username != "" {
  186. guild.Presences[i].User.Username = presence.User.Username
  187. }
  188. return nil
  189. }
  190. }
  191. guild.Presences = append(guild.Presences, presence)
  192. return nil
  193. }
  194. // PresenceRemove removes a presence from the current world state.
  195. func (s *State) PresenceRemove(guildID string, presence *Presence) error {
  196. if s == nil {
  197. return ErrNilState
  198. }
  199. guild, err := s.Guild(guildID)
  200. if err != nil {
  201. return err
  202. }
  203. s.Lock()
  204. defer s.Unlock()
  205. for i, p := range guild.Presences {
  206. if p.User.ID == presence.User.ID {
  207. guild.Presences = append(guild.Presences[:i], guild.Presences[i+1:]...)
  208. return nil
  209. }
  210. }
  211. return ErrStateNotFound
  212. }
  213. // Presence gets a presence by ID from a guild.
  214. func (s *State) Presence(guildID, userID string) (*Presence, error) {
  215. if s == nil {
  216. return nil, ErrNilState
  217. }
  218. guild, err := s.Guild(guildID)
  219. if err != nil {
  220. return nil, err
  221. }
  222. for _, p := range guild.Presences {
  223. if p.User.ID == userID {
  224. return p, nil
  225. }
  226. }
  227. return nil, ErrStateNotFound
  228. }
  229. // TODO: Consider moving Guild state update methods onto *Guild.
  230. // MemberAdd adds a member to the current world state, or
  231. // updates it if it already exists.
  232. func (s *State) MemberAdd(member *Member) error {
  233. if s == nil {
  234. return ErrNilState
  235. }
  236. guild, err := s.Guild(member.GuildID)
  237. if err != nil {
  238. return err
  239. }
  240. s.Lock()
  241. defer s.Unlock()
  242. members, ok := s.memberMap[member.GuildID]
  243. if !ok {
  244. return ErrStateNotFound
  245. }
  246. m, ok := members[member.User.ID]
  247. if !ok {
  248. members[member.User.ID] = member
  249. guild.Members = append(guild.Members, member)
  250. } else {
  251. // We are about to replace `m` in the state with `member`, but first we need to
  252. // make sure we preserve any fields that the `member` doesn't contain from `m`.
  253. if member.JoinedAt == "" {
  254. member.JoinedAt = m.JoinedAt
  255. }
  256. *m = *member
  257. }
  258. return nil
  259. }
  260. // MemberRemove removes a member from current world state.
  261. func (s *State) MemberRemove(member *Member) error {
  262. if s == nil {
  263. return ErrNilState
  264. }
  265. guild, err := s.Guild(member.GuildID)
  266. if err != nil {
  267. return err
  268. }
  269. s.Lock()
  270. defer s.Unlock()
  271. members, ok := s.memberMap[member.GuildID]
  272. if !ok {
  273. return ErrStateNotFound
  274. }
  275. _, ok = members[member.User.ID]
  276. if !ok {
  277. return ErrStateNotFound
  278. }
  279. delete(members, member.User.ID)
  280. for i, m := range guild.Members {
  281. if m.User.ID == member.User.ID {
  282. guild.Members = append(guild.Members[:i], guild.Members[i+1:]...)
  283. return nil
  284. }
  285. }
  286. return ErrStateNotFound
  287. }
  288. // Member gets a member by ID from a guild.
  289. func (s *State) Member(guildID, userID string) (*Member, error) {
  290. if s == nil {
  291. return nil, ErrNilState
  292. }
  293. s.RLock()
  294. defer s.RUnlock()
  295. members, ok := s.memberMap[guildID]
  296. if !ok {
  297. return nil, ErrStateNotFound
  298. }
  299. m, ok := members[userID]
  300. if ok {
  301. return m, nil
  302. }
  303. return nil, ErrStateNotFound
  304. }
  305. // RoleAdd adds a role to the current world state, or
  306. // updates it if it already exists.
  307. func (s *State) RoleAdd(guildID string, role *Role) error {
  308. if s == nil {
  309. return ErrNilState
  310. }
  311. guild, err := s.Guild(guildID)
  312. if err != nil {
  313. return err
  314. }
  315. s.Lock()
  316. defer s.Unlock()
  317. for i, r := range guild.Roles {
  318. if r.ID == role.ID {
  319. guild.Roles[i] = role
  320. return nil
  321. }
  322. }
  323. guild.Roles = append(guild.Roles, role)
  324. return nil
  325. }
  326. // RoleRemove removes a role from current world state by ID.
  327. func (s *State) RoleRemove(guildID, roleID string) error {
  328. if s == nil {
  329. return ErrNilState
  330. }
  331. guild, err := s.Guild(guildID)
  332. if err != nil {
  333. return err
  334. }
  335. s.Lock()
  336. defer s.Unlock()
  337. for i, r := range guild.Roles {
  338. if r.ID == roleID {
  339. guild.Roles = append(guild.Roles[:i], guild.Roles[i+1:]...)
  340. return nil
  341. }
  342. }
  343. return ErrStateNotFound
  344. }
  345. // Role gets a role by ID from a guild.
  346. func (s *State) Role(guildID, roleID string) (*Role, error) {
  347. if s == nil {
  348. return nil, ErrNilState
  349. }
  350. guild, err := s.Guild(guildID)
  351. if err != nil {
  352. return nil, err
  353. }
  354. s.RLock()
  355. defer s.RUnlock()
  356. for _, r := range guild.Roles {
  357. if r.ID == roleID {
  358. return r, nil
  359. }
  360. }
  361. return nil, ErrStateNotFound
  362. }
  363. // ChannelAdd adds a channel to the current world state, or
  364. // updates it if it already exists.
  365. // Channels may exist either as PrivateChannels or inside
  366. // a guild.
  367. func (s *State) ChannelAdd(channel *Channel) error {
  368. if s == nil {
  369. return ErrNilState
  370. }
  371. s.Lock()
  372. defer s.Unlock()
  373. // If the channel exists, replace it
  374. if c, ok := s.channelMap[channel.ID]; ok {
  375. if channel.Messages == nil {
  376. channel.Messages = c.Messages
  377. }
  378. if channel.PermissionOverwrites == nil {
  379. channel.PermissionOverwrites = c.PermissionOverwrites
  380. }
  381. *c = *channel
  382. return nil
  383. }
  384. if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM {
  385. s.PrivateChannels = append(s.PrivateChannels, channel)
  386. } else {
  387. guild, ok := s.guildMap[channel.GuildID]
  388. if !ok {
  389. return ErrStateNotFound
  390. }
  391. guild.Channels = append(guild.Channels, channel)
  392. }
  393. s.channelMap[channel.ID] = channel
  394. return nil
  395. }
  396. // ChannelRemove removes a channel from current world state.
  397. func (s *State) ChannelRemove(channel *Channel) error {
  398. if s == nil {
  399. return ErrNilState
  400. }
  401. _, err := s.Channel(channel.ID)
  402. if err != nil {
  403. return err
  404. }
  405. if channel.Type == ChannelTypeDM || channel.Type == ChannelTypeGroupDM {
  406. s.Lock()
  407. defer s.Unlock()
  408. for i, c := range s.PrivateChannels {
  409. if c.ID == channel.ID {
  410. s.PrivateChannels = append(s.PrivateChannels[:i], s.PrivateChannels[i+1:]...)
  411. break
  412. }
  413. }
  414. } else {
  415. guild, err := s.Guild(channel.GuildID)
  416. if err != nil {
  417. return err
  418. }
  419. s.Lock()
  420. defer s.Unlock()
  421. for i, c := range guild.Channels {
  422. if c.ID == channel.ID {
  423. guild.Channels = append(guild.Channels[:i], guild.Channels[i+1:]...)
  424. break
  425. }
  426. }
  427. }
  428. delete(s.channelMap, channel.ID)
  429. return nil
  430. }
  431. // GuildChannel gets a channel by ID from a guild.
  432. // This method is Deprecated, use Channel(channelID)
  433. func (s *State) GuildChannel(guildID, channelID string) (*Channel, error) {
  434. return s.Channel(channelID)
  435. }
  436. // PrivateChannel gets a private channel by ID.
  437. // This method is Deprecated, use Channel(channelID)
  438. func (s *State) PrivateChannel(channelID string) (*Channel, error) {
  439. return s.Channel(channelID)
  440. }
  441. // Channel gets a channel by ID, it will look in all guilds and private channels.
  442. func (s *State) Channel(channelID string) (*Channel, error) {
  443. if s == nil {
  444. return nil, ErrNilState
  445. }
  446. s.RLock()
  447. defer s.RUnlock()
  448. if c, ok := s.channelMap[channelID]; ok {
  449. return c, nil
  450. }
  451. return nil, ErrStateNotFound
  452. }
  453. // Emoji returns an emoji for a guild and emoji id.
  454. func (s *State) Emoji(guildID, emojiID string) (*Emoji, error) {
  455. if s == nil {
  456. return nil, ErrNilState
  457. }
  458. guild, err := s.Guild(guildID)
  459. if err != nil {
  460. return nil, err
  461. }
  462. s.RLock()
  463. defer s.RUnlock()
  464. for _, e := range guild.Emojis {
  465. if e.ID == emojiID {
  466. return e, nil
  467. }
  468. }
  469. return nil, ErrStateNotFound
  470. }
  471. // EmojiAdd adds an emoji to the current world state.
  472. func (s *State) EmojiAdd(guildID string, emoji *Emoji) error {
  473. if s == nil {
  474. return ErrNilState
  475. }
  476. guild, err := s.Guild(guildID)
  477. if err != nil {
  478. return err
  479. }
  480. s.Lock()
  481. defer s.Unlock()
  482. for i, e := range guild.Emojis {
  483. if e.ID == emoji.ID {
  484. guild.Emojis[i] = emoji
  485. return nil
  486. }
  487. }
  488. guild.Emojis = append(guild.Emojis, emoji)
  489. return nil
  490. }
  491. // EmojisAdd adds multiple emojis to the world state.
  492. func (s *State) EmojisAdd(guildID string, emojis []*Emoji) error {
  493. for _, e := range emojis {
  494. if err := s.EmojiAdd(guildID, e); err != nil {
  495. return err
  496. }
  497. }
  498. return nil
  499. }
  500. // MessageAdd adds a message to the current world state, or updates it if it exists.
  501. // If the channel cannot be found, the message is discarded.
  502. // Messages are kept in state up to s.MaxMessageCount per channel.
  503. func (s *State) MessageAdd(message *Message) error {
  504. if s == nil {
  505. return ErrNilState
  506. }
  507. c, err := s.Channel(message.ChannelID)
  508. if err != nil {
  509. return err
  510. }
  511. s.Lock()
  512. defer s.Unlock()
  513. // If the message exists, merge in the new message contents.
  514. for _, m := range c.Messages {
  515. if m.ID == message.ID {
  516. if message.Content != "" {
  517. m.Content = message.Content
  518. }
  519. if message.EditedTimestamp != "" {
  520. m.EditedTimestamp = message.EditedTimestamp
  521. }
  522. if message.Mentions != nil {
  523. m.Mentions = message.Mentions
  524. }
  525. if message.Embeds != nil {
  526. m.Embeds = message.Embeds
  527. }
  528. if message.Attachments != nil {
  529. m.Attachments = message.Attachments
  530. }
  531. if message.Timestamp != "" {
  532. m.Timestamp = message.Timestamp
  533. }
  534. if message.Author != nil {
  535. m.Author = message.Author
  536. }
  537. return nil
  538. }
  539. }
  540. c.Messages = append(c.Messages, message)
  541. if len(c.Messages) > s.MaxMessageCount {
  542. c.Messages = c.Messages[len(c.Messages)-s.MaxMessageCount:]
  543. }
  544. return nil
  545. }
  546. // MessageRemove removes a message from the world state.
  547. func (s *State) MessageRemove(message *Message) error {
  548. if s == nil {
  549. return ErrNilState
  550. }
  551. return s.messageRemoveByID(message.ChannelID, message.ID)
  552. }
  553. // messageRemoveByID removes a message by channelID and messageID from the world state.
  554. func (s *State) messageRemoveByID(channelID, messageID string) error {
  555. c, err := s.Channel(channelID)
  556. if err != nil {
  557. return err
  558. }
  559. s.Lock()
  560. defer s.Unlock()
  561. for i, m := range c.Messages {
  562. if m.ID == messageID {
  563. c.Messages = append(c.Messages[:i], c.Messages[i+1:]...)
  564. return nil
  565. }
  566. }
  567. return ErrStateNotFound
  568. }
  569. func (s *State) voiceStateUpdate(update *VoiceStateUpdate) error {
  570. guild, err := s.Guild(update.GuildID)
  571. if err != nil {
  572. return err
  573. }
  574. s.Lock()
  575. defer s.Unlock()
  576. // Handle Leaving Channel
  577. if update.ChannelID == "" {
  578. for i, state := range guild.VoiceStates {
  579. if state.UserID == update.UserID {
  580. guild.VoiceStates = append(guild.VoiceStates[:i], guild.VoiceStates[i+1:]...)
  581. return nil
  582. }
  583. }
  584. } else {
  585. for i, state := range guild.VoiceStates {
  586. if state.UserID == update.UserID {
  587. guild.VoiceStates[i] = update.VoiceState
  588. return nil
  589. }
  590. }
  591. guild.VoiceStates = append(guild.VoiceStates, update.VoiceState)
  592. }
  593. return nil
  594. }
  595. // Message gets a message by channel and message ID.
  596. func (s *State) Message(channelID, messageID string) (*Message, error) {
  597. if s == nil {
  598. return nil, ErrNilState
  599. }
  600. c, err := s.Channel(channelID)
  601. if err != nil {
  602. return nil, err
  603. }
  604. s.RLock()
  605. defer s.RUnlock()
  606. for _, m := range c.Messages {
  607. if m.ID == messageID {
  608. return m, nil
  609. }
  610. }
  611. return nil, ErrStateNotFound
  612. }
  613. // OnReady takes a Ready event and updates all internal state.
  614. func (s *State) onReady(se *Session, r *Ready) (err error) {
  615. if s == nil {
  616. return ErrNilState
  617. }
  618. s.Lock()
  619. defer s.Unlock()
  620. // We must track at least the current user for Voice, even
  621. // if state is disabled, store the bare essentials.
  622. if !se.StateEnabled {
  623. ready := Ready{
  624. Version: r.Version,
  625. SessionID: r.SessionID,
  626. User: r.User,
  627. }
  628. s.Ready = ready
  629. return nil
  630. }
  631. s.Ready = *r
  632. for _, g := range s.Guilds {
  633. s.guildMap[g.ID] = g
  634. s.createMemberMap(g)
  635. for _, c := range g.Channels {
  636. s.channelMap[c.ID] = c
  637. }
  638. }
  639. for _, c := range s.PrivateChannels {
  640. s.channelMap[c.ID] = c
  641. }
  642. return nil
  643. }
  644. // OnInterface handles all events related to states.
  645. func (s *State) OnInterface(se *Session, i interface{}) (err error) {
  646. if s == nil {
  647. return ErrNilState
  648. }
  649. r, ok := i.(*Ready)
  650. if ok {
  651. return s.onReady(se, r)
  652. }
  653. if !se.StateEnabled {
  654. return nil
  655. }
  656. switch t := i.(type) {
  657. case *GuildCreate:
  658. err = s.GuildAdd(t.Guild)
  659. case *GuildUpdate:
  660. err = s.GuildAdd(t.Guild)
  661. case *GuildDelete:
  662. err = s.GuildRemove(t.Guild)
  663. case *GuildMemberAdd:
  664. if s.TrackMembers {
  665. err = s.MemberAdd(t.Member)
  666. }
  667. case *GuildMemberUpdate:
  668. if s.TrackMembers {
  669. err = s.MemberAdd(t.Member)
  670. }
  671. case *GuildMemberRemove:
  672. if s.TrackMembers {
  673. err = s.MemberRemove(t.Member)
  674. }
  675. case *GuildMembersChunk:
  676. if s.TrackMembers {
  677. for i := range t.Members {
  678. t.Members[i].GuildID = t.GuildID
  679. err = s.MemberAdd(t.Members[i])
  680. }
  681. }
  682. case *GuildRoleCreate:
  683. if s.TrackRoles {
  684. err = s.RoleAdd(t.GuildID, t.Role)
  685. }
  686. case *GuildRoleUpdate:
  687. if s.TrackRoles {
  688. err = s.RoleAdd(t.GuildID, t.Role)
  689. }
  690. case *GuildRoleDelete:
  691. if s.TrackRoles {
  692. err = s.RoleRemove(t.GuildID, t.RoleID)
  693. }
  694. case *GuildEmojisUpdate:
  695. if s.TrackEmojis {
  696. err = s.EmojisAdd(t.GuildID, t.Emojis)
  697. }
  698. case *ChannelCreate:
  699. if s.TrackChannels {
  700. err = s.ChannelAdd(t.Channel)
  701. }
  702. case *ChannelUpdate:
  703. if s.TrackChannels {
  704. err = s.ChannelAdd(t.Channel)
  705. }
  706. case *ChannelDelete:
  707. if s.TrackChannels {
  708. err = s.ChannelRemove(t.Channel)
  709. }
  710. case *MessageCreate:
  711. if s.MaxMessageCount != 0 {
  712. err = s.MessageAdd(t.Message)
  713. }
  714. case *MessageUpdate:
  715. if s.MaxMessageCount != 0 {
  716. old, err := s.Message(t.ChannelID, t.ID)
  717. if err == nil {
  718. oldCopy := *old
  719. t.BeforeUpdate = &oldCopy
  720. }
  721. err = s.MessageAdd(t.Message)
  722. }
  723. case *MessageDelete:
  724. if s.MaxMessageCount != 0 {
  725. err = s.MessageRemove(t.Message)
  726. }
  727. case *MessageDeleteBulk:
  728. if s.MaxMessageCount != 0 {
  729. for _, mID := range t.Messages {
  730. s.messageRemoveByID(t.ChannelID, mID)
  731. }
  732. }
  733. case *VoiceStateUpdate:
  734. if s.TrackVoice {
  735. err = s.voiceStateUpdate(t)
  736. }
  737. case *PresenceUpdate:
  738. if s.TrackPresences {
  739. s.PresenceAdd(t.GuildID, &t.Presence)
  740. }
  741. if s.TrackMembers {
  742. if t.Status == StatusOffline {
  743. return
  744. }
  745. var m *Member
  746. m, err = s.Member(t.GuildID, t.User.ID)
  747. if err != nil {
  748. // Member not found; this is a user coming online
  749. m = &Member{
  750. GuildID: t.GuildID,
  751. Nick: t.Nick,
  752. User: t.User,
  753. Roles: t.Roles,
  754. }
  755. } else {
  756. if t.Nick != "" {
  757. m.Nick = t.Nick
  758. }
  759. if t.User.Username != "" {
  760. m.User.Username = t.User.Username
  761. }
  762. // PresenceUpdates always contain a list of roles, so there's no need to check for an empty list here
  763. m.Roles = t.Roles
  764. }
  765. err = s.MemberAdd(m)
  766. }
  767. }
  768. return
  769. }
  770. // UserChannelPermissions returns the permission of a user in a channel.
  771. // userID : The ID of the user to calculate permissions for.
  772. // channelID : The ID of the channel to calculate permission for.
  773. func (s *State) UserChannelPermissions(userID, channelID string) (apermissions int, err error) {
  774. if s == nil {
  775. return 0, ErrNilState
  776. }
  777. channel, err := s.Channel(channelID)
  778. if err != nil {
  779. return
  780. }
  781. guild, err := s.Guild(channel.GuildID)
  782. if err != nil {
  783. return
  784. }
  785. if userID == guild.OwnerID {
  786. apermissions = PermissionAll
  787. return
  788. }
  789. member, err := s.Member(guild.ID, userID)
  790. if err != nil {
  791. return
  792. }
  793. return memberPermissions(guild, channel, member), nil
  794. }
  795. // UserColor returns the color of a user in a channel.
  796. // While colors are defined at a Guild level, determining for a channel is more useful in message handlers.
  797. // 0 is returned in cases of error, which is the color of @everyone.
  798. // userID : The ID of the user to calculate the color for.
  799. // channelID : The ID of the channel to calculate the color for.
  800. func (s *State) UserColor(userID, channelID string) int {
  801. if s == nil {
  802. return 0
  803. }
  804. channel, err := s.Channel(channelID)
  805. if err != nil {
  806. return 0
  807. }
  808. guild, err := s.Guild(channel.GuildID)
  809. if err != nil {
  810. return 0
  811. }
  812. member, err := s.Member(guild.ID, userID)
  813. if err != nil {
  814. return 0
  815. }
  816. roles := Roles(guild.Roles)
  817. sort.Sort(roles)
  818. for _, role := range roles {
  819. for _, roleID := range member.Roles {
  820. if role.ID == roleID {
  821. if role.Color != 0 {
  822. return role.Color
  823. }
  824. }
  825. }
  826. }
  827. return 0
  828. }