Skip to content

Instantly share code, notes, and snippets.

@foxfirecodes
Last active August 31, 2020 21:28
Show Gist options
  • Save foxfirecodes/6e9104414993030cb31cadf268a10c3b to your computer and use it in GitHub Desktop.
Save foxfirecodes/6e9104414993030cb31cadf268a10c3b to your computer and use it in GitHub Desktop.
Discord.js snippets for diffing changes of Discord permission overwrites

These are two potential scripts for computing (sane) diffs of permission overwrite changes on Discord channels with Discord.js.

bot.on('channelUpdate', (oldChannel, newChannel) => {
if (!oldChannel.guild) {
return
}
// get all roles/members that did or did not have overwrites:
const overwriteChanges = [...oldChannel.permissionOverwrites.keyArray(), ...newChannel.permissionOverwrites.keyArray()]
// filter out duplicate role/member IDs
.reduce((out, next) => out.includes(next) ? out : out.concat(next), [])
// map to pairs
.map(id => ({ id, before: oldChannel.permissionOverwrites.get(id), after: newChannel.permissionOverwrites.get(id) }))
// convert the PermissionOverwrites objects into easier to deal with null-safe types
.map(({ id, before, after }) => ({
id,
// get the overwrite type (role or member) from whichever object exists
type: before ? before.type : after.type,
before: {
// instead of having potentially null values for before/after, just use an empty array
allow: before ? before.allow.toArray() : [],
deny: before ? before.deny.toArray() : []
},
after: {
allow: after ? after.allow.toArray() : [],
deny: after ? after.deny.toArray() : []
}
}))
// find diffs
.map(({ id, type, before, after }) => ({
// preserve the ID & type
id,
type,
// compute permissions that are removed
// if the permission overwrite for the user/role wasn't deleted (after), filter out things that still exist (weren't deleted)
removed: [...before.allow, ...before.deny].filter(it => ![...after.allow, ...after.deny].includes(it)),
// if there are permission overwrites for the user/role after the update, make sure that anything that previously existed was removed
newlyAllowed: after.allow.filter(it => !before.allow.includes(it)),
newlyDenied: after.deny.filter(it => !before.deny.includes(it))
}))
// filter to only overwrites that changed in some way
.filter(({ removed, newlyAllowed, newlyDenied }) => removed.length || newlyAllowed.length || newlyDenied.length)
if (overwriteChanges.length < 1) {
// no changes happened to permission in this channel update, so ignore
return
}
// overwriteChanges is an array of permission overwrites that have changed, stored as objects in the format of:
// {
// id: string - the id of the role/member that changed
// type: string - either 'role' or 'member'
// removed: string[] - any permissions that are no longer allowed/denied
// newlyAllowed: string[] - the newly allowed permissions
// newlyDenied: string[] - the newly denied permissions
// }
console.log(`Received channel permission update for #${oldChannel.name} in ${oldChannel.guild.name}:`)
overwriteChanges.forEach(overwrite => console.log(overwrite))
});
bot.on('channelUpdate', (oldChannel, newChannel) => {
if (!oldChannel.guild) {
return
}
// get all roles/members that did or did not have overwrites:
const overwriteChanges = [...oldChannel.permissionOverwrites.keyArray(), ...newChannel.permissionOverwrites.keyArray()]
// filter out duplicate role/member IDs
.reduce((out, next) => out.includes(next) ? out : out.concat(next), [])
// map to pairs
.map(id => ({ id, before: oldChannel.permissionOverwrites.get(id), after: newChannel.permissionOverwrites.get(id) }))
// find diffs
.map(({ id, before, after }) => ({
// preserve the ID
id,
// get the overwrite type (role or member) from whichever object exists
type: before ? before.type : after.type,
removed: !before ? [] : [...before.allow.toArray(), ...before.deny.toArray()]
// if the permission overwrite for the user/role wasn't deleted (after), filter out things that still exist (weren't deleted)
.filter(it => after ? ![...after.allow.toArray(), ...after.deny.toArray()].includes(it) : true),
// if there are permission overwrites for the user/role after the update, make sure that anything that previously existed was removed
newlyAllowed: !after ? [] : (before ? after.allow.remove(before.allow) : after.allow).toArray(),
newlyDenied: !after ? [] : (before ? after.deny.remove(before.deny) : after.deny).toArray()
}))
// filter to only overwrites that changed in some way
.filter(({ removed, newlyAllowed, newlyDenied }) => removed.length || newlyAllowed.length || newlyDenied.length)
if (overwriteChanges.length < 1) {
// no changes happened to permission in this channel update, so ignore
return
}
// overwriteChanges is an array of permission overwrites that have changed, stored as objects in the format of:
// {
// id: string - the id of the role/member that changed
// type: string - either 'role' or 'member'
// removed: string[] - any permissions that are no longer allowed/denied
// newlyAllowed: string[] - the newly allowed permissions
// newlyDenied: string[] - the newly denied permissions
// }
console.log(`Received channel permission update for #${oldChannel.name} in ${oldChannel.guild.name}:`)
overwriteChanges.forEach(overwrite => console.log(overwrite))
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment