From 7ab242d361c0dd43613f8c188e4978b4d18a8c89 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Fri, 16 Oct 2020 18:09:59 +1100 Subject: [PATCH] Add State helper methods for reading permissions and role colors from Message roles. --- event.go | 2 +- restapi.go | 10 ++++---- state.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/event.go b/event.go index 67c5f7d..46e1937 100644 --- a/event.go +++ b/event.go @@ -244,4 +244,4 @@ func (s *Session) onReady(r *Ready) { // Store the SessionID within the Session struct. s.sessionID = r.SessionID -} +} \ No newline at end of file diff --git a/restapi.go b/restapi.go index b5e67cb..9432194 100644 --- a/restapi.go +++ b/restapi.go @@ -502,14 +502,12 @@ func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions } } - return memberPermissions(guild, channel, member), nil + return memberPermissions(guild, channel, userID, member.Roles), nil } // Calculates the permissions for a member. // https://support.discord.com/hc/en-us/articles/206141927-How-is-the-permission-hierarchy-structured- -func memberPermissions(guild *Guild, channel *Channel, member *Member) (apermissions int) { - userID := member.User.ID - +func memberPermissions(guild *Guild, channel *Channel, userID string, roles []string) (apermissions int) { if userID == guild.OwnerID { apermissions = PermissionAll return @@ -523,7 +521,7 @@ func memberPermissions(guild *Guild, channel *Channel, member *Member) (apermiss } for _, role := range guild.Roles { - for _, roleID := range member.Roles { + for _, roleID := range roles { if role.ID == roleID { apermissions |= role.Permissions break @@ -549,7 +547,7 @@ func memberPermissions(guild *Guild, channel *Channel, member *Member) (apermiss // Member overwrites can override role overrides, so do two passes for _, overwrite := range channel.PermissionOverwrites { - for _, roleID := range member.Roles { + for _, roleID := range roles { if overwrite.Type == "role" && roleID == overwrite.ID { denies |= overwrite.Deny allows |= overwrite.Allow diff --git a/state.go b/state.go index 80bd8df..be5d6b6 100644 --- a/state.go +++ b/state.go @@ -1,3 +1,4 @@ + // Discordgo - Discord bindings for Go // Available at https://github.com/bwmarrin/discordgo @@ -25,6 +26,11 @@ var ErrNilState = errors.New("state not instantiated, please use discordgo.New() // requested is not found var ErrStateNotFound = errors.New("state cache not found") +// ErrMessageIncompletePermissions is returned when the message +// requested for permissions does not contain enough data to +// generate the permissions. +var ErrMessageIncompletePermissions = errors.New("message incomplete, unable to determine permissions") + // A State contains the current known state. // As discord sends this in a READY blob, it seems reasonable to simply // use that struct as the data store. @@ -980,17 +986,34 @@ func (s *State) UserChannelPermissions(userID, channelID string) (apermissions i return } - if userID == guild.OwnerID { - apermissions = PermissionAll - return - } - member, err := s.Member(guild.ID, userID) if err != nil { return } - return memberPermissions(guild, channel, member), nil + return memberPermissions(guild, channel, userID, member.Roles), nil +} + +func (s *State) MessagePermissions(message *Message) (apermissions int, err error) { + if s == nil { + return 0, ErrNilState + } + + if message.Author == nil || message.Member == nil { + return 0, ErrMessageIncompletePermissions + } + + channel, err := s.Channel(message.ChannelID) + if err != nil { + return + } + + guild, err := s.Guild(channel.GuildID) + if err != nil { + return + } + + return memberPermissions(guild, channel, message.Author.ID, message.Member.Roles), nil } // UserColor returns the color of a user in a channel. @@ -1018,11 +1041,37 @@ func (s *State) UserColor(userID, channelID string) int { return 0 } + return firstRoleColorColor(guild, member.Roles) +} + +func (s *State) MessageColor(message *Message) int { + if s == nil { + return 0 + } + + if message.Member == nil || message.Member.Roles == nil { + return 0 + } + + channel, err := s.Channel(message.ChannelID) + if err != nil { + return 0 + } + + guild, err := s.Guild(channel.GuildID) + if err != nil { + return 0 + } + + return firstRoleColorColor(guild, message.Member.Roles) +} + +func firstRoleColorColor(guild *Guild, memberRoles []string) int { roles := Roles(guild.Roles) sort.Sort(roles) for _, role := range roles { - for _, roleID := range member.Roles { + for _, roleID := range memberRoles { if role.ID == roleID { if role.Color != 0 { return role.Color @@ -1031,5 +1080,11 @@ func (s *State) UserColor(userID, channelID string) int { } } + for _, role := range roles { + if role.ID == guild.ID { + return role.Color + } + } + return 0 }