diff --git a/src/models/Channel.ts b/src/models/Channel.ts
index 36f5e83d..3c63f80f 100644
--- a/src/models/Channel.ts
+++ b/src/models/Channel.ts
@@ -47,12 +47,19 @@ export interface GuildChannel extends Channel {
guild_id: bigint;
position: number;
parent_id?: bigint;
- permission_overwrites: {
- allow: bigint;
- deny: bigint;
- id: bigint;
- type: number;
- }[];
+ permission_overwrites: ChannelPermissionOverwrite[];
+}
+
+export interface ChannelPermissionOverwrite {
+ allow: bigint;
+ deny: bigint;
+ id: bigint;
+ type: ChannelPermissionOverwriteType;
+}
+
+export enum ChannelPermissionOverwriteType {
+ role = 0,
+ member = 1,
}
export interface VoiceChannel extends GuildChannel {}
diff --git a/src/models/Member.ts b/src/models/Member.ts
index d9f34ac8..dd26782f 100644
--- a/src/models/Member.ts
+++ b/src/models/Member.ts
@@ -3,6 +3,7 @@ import { Schema, model, Types, Document } from "mongoose";
export interface Member extends Document {
id: bigint;
+ guild_id: bigint;
nick?: string;
roles: bigint[];
joined_at: number;
@@ -42,6 +43,7 @@ const MuteConfig = {
export const MemberSchema = new Schema({
id: Types.Long,
+ guild_id: Types.Long,
nick: String,
roles: [Types.Long],
joined_at: Number,
diff --git a/src/models/Message.ts b/src/models/Message.ts
index 22569d8f..9b3602c4 100644
--- a/src/models/Message.ts
+++ b/src/models/Message.ts
@@ -3,6 +3,7 @@ import { ChannelType } from "./Channel";
export interface Message extends Document {
id: bigint;
+ channel_id: bigint;
author_id?: bigint;
webhook_id?: bigint;
application_id: bigint;
@@ -188,6 +189,7 @@ const Embed = {
export const MessageSchema = new Schema({
id: Types.Long,
+ channel_id: Types.Long,
author_id: Types.Long,
webhook_id: Types.Long,
application_id: Types.Long,
diff --git a/src/models/Role.ts b/src/models/Role.ts
index d35bd57c..b6cba2f8 100644
--- a/src/models/Role.ts
+++ b/src/models/Role.ts
@@ -2,6 +2,7 @@ import { Schema, model, Types, Document } from "mongoose";
export interface Role extends Document {
id: bigint;
+ guild_id: bigint;
color: number;
hoist: boolean;
managed: boolean;
@@ -16,6 +17,7 @@ export interface Role extends Document {
export const RoleSchema = new Schema({
id: Types.Long,
+ guild_id: Types.Long,
color: Number,
hoist: Boolean,
managed: Boolean,
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;
+ }
}
|