-
Notifications
You must be signed in to change notification settings - Fork 915
/
permissions.go
105 lines (87 loc) · 3.07 KB
/
permissions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package dstate
import "github.com/botlabs-gg/yagpdb/v2/lib/discordgo"
const AllPermissions int64 = discordgo.PermissionAll
// Apply this mask to channel permissions to filter them out
// discord performs no server side validation so this is needed
// as to not run into some really weird situations
const ChannelPermsMask = ^(discordgo.PermissionAdministrator |
discordgo.PermissionManageServer |
discordgo.PermissionChangeNickname |
discordgo.PermissionManageServer |
discordgo.PermissionManageRoles |
discordgo.PermissionKickMembers |
discordgo.PermissionBanMembers)
// CalculatePermissions calculates the full permissions of a user
func CalculatePermissions(g *GuildState, guildRoles []discordgo.Role, overwrites []discordgo.PermissionOverwrite, memberID int64, roles []int64) (perms int64) {
perms = CalculateBasePermissions(g.ID, g.OwnerID, guildRoles, memberID, roles)
perms = ApplyChannelPermissions(perms, g.ID, overwrites, memberID, roles)
return perms
}
// CalculateBasePermissions calculates the guild scope permissions, excluding channel overwrites
func CalculateBasePermissions(guildID int64, ownerID int64, guildRoles []discordgo.Role, memberID int64, roles []int64) (perms int64) {
if ownerID == memberID {
return AllPermissions
}
// everyone role first
for _, role := range guildRoles {
if role.ID == guildID {
perms |= int64(role.Permissions)
break
}
}
// member roles
for _, role := range guildRoles {
for _, roleID := range roles {
if role.ID == roleID {
perms |= int64(role.Permissions)
break
}
}
}
// Administrator bypasses channel overrides
if perms&discordgo.PermissionAdministrator == discordgo.PermissionAdministrator {
return AllPermissions
}
return perms
}
// ApplyChannelPermissions applies the channel permission overwrites to the input perms
func ApplyChannelPermissions(perms int64, guildID int64, overwrites []discordgo.PermissionOverwrite, memberID int64, roles []int64) int64 {
if len(overwrites) == 0 {
return perms
}
// If user is admin or owner, overrides dont apply
if perms == AllPermissions {
return perms
}
// Apply chanel overwrites
// Apply @everyone overrides from the channel.
for _, overwrite := range overwrites {
if guildID == overwrite.ID {
perms &= ^int64(overwrite.Deny & ChannelPermsMask)
perms |= int64(overwrite.Allow & ChannelPermsMask)
break
}
}
denies := int64(0)
allows := int64(0)
// Member overwrites can override role overrides, so do two passes with roles first
for _, overwrite := range overwrites {
for _, roleID := range roles {
if overwrite.Type == discordgo.PermissionOverwriteTypeRole && roleID == overwrite.ID {
denies |= int64(overwrite.Deny & ChannelPermsMask)
allows |= int64(overwrite.Allow & ChannelPermsMask)
break
}
}
}
perms &= ^int64(denies)
perms |= int64(allows)
for _, overwrite := range overwrites {
if overwrite.Type == discordgo.PermissionOverwriteTypeMember && overwrite.ID == memberID {
perms &= ^int64(overwrite.Deny & ChannelPermsMask)
perms |= int64(overwrite.Allow & ChannelPermsMask)
break
}
}
return perms
}