state.go 21 KB

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