Browse Source

Add State helper methods for reading permissions and role colors from Message roles.

Chris Rhodes 4 years ago
parent
commit
7ab242d361
3 changed files with 65 additions and 12 deletions
  1. 1 1
      event.go
  2. 4 6
      restapi.go
  3. 60 5
      state.go

+ 1 - 1
event.go

@@ -244,4 +244,4 @@ func (s *Session) onReady(r *Ready) {
 
 	// Store the SessionID within the Session struct.
 	s.sessionID = r.SessionID
-}
+}

+ 4 - 6
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

+ 60 - 5
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
+	member, err := s.Member(guild.ID, userID)
+	if err != nil {
 		return
 	}
 
-	member, err := s.Member(guild.ID, userID)
+	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, member), nil
+	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
 }