summary refs log tree commit diff
path: root/src/util/Permissions.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/Permissions.ts')
-rw-r--r--src/util/Permissions.ts47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/util/Permissions.ts b/src/util/Permissions.ts
index c3dcdb53..89e1d1d3 100644
--- a/src/util/Permissions.ts
+++ b/src/util/Permissions.ts
@@ -1,6 +1,8 @@
 // https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
 // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
 
+import { ChannelPermissionOverwrite } from "../models/Channel";
+import { Role } from "../models/Role";
 import { BitField } from "./BitField";
 
 export type PermissionResolvable = string | number | Permissions | PermissionResolvable[];
@@ -50,4 +52,49 @@ export class Permissions extends BitField {
 	has(permission: PermissionResolvable, checkAdmin = true) {
 		return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission);
 	}
+
+	static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) {
+		// channelOverwrites.filter((x) => x.type === 1 && x.id !== user.id);
+		return overwrites.reduce((permission, overwrite) => {
+			// apply disallowed permission
+			// * permission: current calculated permission (e.g. 010)
+			// * deny contains all denied permissions (e.g. 011)
+			// * allow contains all explicitly allowed permisions (e.g. 100)
+			return (permission & ~overwrite.deny) | overwrite.allow;
+			// ~ operator inverts deny (e.g. 011 -> 100)
+			// & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000)
+			// | operators adds both together (e.g. 000 + 100 -> 100)
+		}, 0n ?? init);
+	}
+
+	static rolePermission(roles: Role[]) {
+		// adds all permissions of all roles together (Bit OR)
+		return roles.reduce((permission, role) => permission | role.permissions, 0n);
+	}
+
+	static finalPermission({
+		user,
+		guild,
+		channel,
+	}: {
+		user: { id: bigint; roles: bigint[] };
+		guild: { roles: Role[] };
+		channel?: {
+			overwrites: ChannelPermissionOverwrite[];
+		};
+	}) {
+		let roles = guild.roles.filter((x) => user.roles.includes(x.id));
+		let permission = Permissions.rolePermission(roles);
+
+		if (channel?.overwrites) {
+			let overwrites = channel.overwrites.filter((x) => {
+				if (x.type === 0 && user.roles.includes(x.id)) return true;
+				if (x.type === 1 && x.id == user.id) return true;
+				return false;
+			});
+			permission = Permissions.channelPermission(overwrites, permission);
+		}
+
+		return permission;
+	}
 }