discord-self-lite 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-self-lite",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Lightweight Discord selfbot library",
5
5
  "keywords": [
6
6
  "discord",
@@ -0,0 +1,110 @@
1
+ /**
2
+ * A BitField is a data structure that makes it easy to interact with a bitfield.
3
+ */
4
+ class BitField {
5
+ /**
6
+ * @param {BitFieldResolvable} [bits=BitField.defaultBit] Bit(s) to read from
7
+ */
8
+ constructor(bits = BitField.defaultBit) {
9
+ /**
10
+ * Bitfield of the packed bits
11
+ * @type {bigint}
12
+ */
13
+ this.bitfield = BitField.resolve(bits);
14
+ }
15
+
16
+ /**
17
+ * Checks whether the bitfield has a bit, or any of multiple bits.
18
+ * @param {BitFieldResolvable} bit Bit(s) to check for
19
+ * @returns {boolean}
20
+ */
21
+ any(bit) {
22
+ return (this.bitfield & BitField.resolve(bit)) !== BitField.defaultBit;
23
+ }
24
+
25
+ /**
26
+ * Checks whether the bitfield has a bit, or multiple bits.
27
+ * @param {BitFieldResolvable} bit Bit(s) to check for
28
+ * @returns {boolean}
29
+ */
30
+ has(bit) {
31
+ bit = BitField.resolve(bit);
32
+ return (this.bitfield & bit) === bit;
33
+ }
34
+
35
+ /**
36
+ * Gets all given bits that are missing from the bitfield.
37
+ * @param {BitFieldResolvable} bits Bit(s) to check for
38
+ * @returns {string[]}
39
+ */
40
+ missing(bits) {
41
+ const res = [];
42
+ const bit = BitField.resolve(bits);
43
+
44
+ for (const [flag, value] of Object.entries(this.constructor.FLAGS)) {
45
+ if ((bit & value) !== value) continue;
46
+ if ((this.bitfield & value) === value) continue;
47
+ res.push(flag);
48
+ }
49
+
50
+ return res;
51
+ }
52
+
53
+ /**
54
+ * Gets an {@link Array} of bitfield names based on the bits available.
55
+ * @param {boolean} [has=true] Whether to show bits that are set
56
+ * @returns {string[]}
57
+ */
58
+ toArray(has = true) {
59
+ const arr = [];
60
+
61
+ for (const [flag, value] of Object.entries(this.constructor.FLAGS)) {
62
+ if (has) {
63
+ if ((this.bitfield & value) === value) arr.push(flag);
64
+ } else {
65
+ if ((this.bitfield & value) !== value) arr.push(flag);
66
+ }
67
+ }
68
+
69
+ return arr;
70
+ }
71
+
72
+ /**
73
+ * Data that can be resolved to give a bitfield. This can be:
74
+ * * A string (see {@link BitField.FLAGS})
75
+ * * A bit number
76
+ * * An instance of BitField
77
+ * * An Array of BitFieldResolvable
78
+ * @typedef {string|bigint|BitField|BitFieldResolvable[]} BitFieldResolvable
79
+ */
80
+
81
+ /**
82
+ * Resolves bitfields to their numeric form.
83
+ * @param {BitFieldResolvable} [bit=BitField.defaultBit] bit(s) to resolve
84
+ * @returns {bigint}
85
+ */
86
+ static resolve(bit = BitField.defaultBit) {
87
+ if (typeof bit === "bigint" && bit >= BitField.defaultBit) return bit;
88
+ if (bit instanceof BitField) return bit.bitfield;
89
+ if (Array.isArray(bit))
90
+ return bit
91
+ .map((p) => this.resolve(p))
92
+ .reduce((prev, p) => prev | p, BitField.defaultBit);
93
+ if (typeof bit === "string") return this.FLAGS[bit];
94
+ throw new TypeError("BitField.resolve: Invalid bitfield");
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Numeric bitfield flags.
100
+ * @type {Object<string, bigint>}
101
+ */
102
+ BitField.FLAGS = {};
103
+
104
+ /**
105
+ * The default bit to use if none are provided.
106
+ * @type {bigint}
107
+ */
108
+ BitField.defaultBit = 0n;
109
+
110
+ module.exports = BitField;
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Represents a Discord channel
3
3
  */
4
+ const Permissions = require("./Permissions");
5
+
4
6
  class Channel {
5
7
  /**
6
8
  * Create a new Channel instance
@@ -161,6 +163,54 @@ class Channel {
161
163
  const guildId = this.data.guild_id;
162
164
  return `https://discord.com/channels/${guildId}/${this.id}`;
163
165
  }
166
+
167
+ /**
168
+ * Check permissions for a member in this channel
169
+ * @param {GuildMember} member - The guild member to check permissions for
170
+ * @returns {Permissions} Permissions bitfield for this member in this channel
171
+ */
172
+ permissionsFor(member) {
173
+ if (!member) return new Permissions(BigInt(0));
174
+
175
+ // Start with the member's base guild permissions
176
+ let permissions = member.permissions.bitfield;
177
+
178
+ // If member has administrator, they have all permissions
179
+ if (member.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) {
180
+ return new Permissions(Permissions.ALL);
181
+ }
182
+
183
+ // Apply channel permission overwrites
184
+ if (this.data.permission_overwrites) {
185
+ const overwrites = this.data.permission_overwrites;
186
+
187
+ // Role overwrites (deny takes precedence over allow)
188
+ const memberRoles = member.roles || [];
189
+ for (const overwrite of overwrites) {
190
+ if (overwrite.type === 0) {
191
+ // Role overwrite
192
+ if (
193
+ memberRoles.includes(overwrite.id) ||
194
+ overwrite.id === this.data.guild_id
195
+ ) {
196
+ permissions &= ~BigInt(overwrite.deny || 0);
197
+ permissions |= BigInt(overwrite.allow || 0);
198
+ }
199
+ }
200
+ }
201
+
202
+ // Member-specific overwrites (takes precedence over role overwrites)
203
+ const memberOverwrite = overwrites.find(
204
+ (ow) => ow.type === 1 && ow.id === member.id,
205
+ );
206
+ if (memberOverwrite) {
207
+ permissions &= ~BigInt(memberOverwrite.deny || 0);
208
+ permissions |= BigInt(memberOverwrite.allow || 0);
209
+ }
210
+ }
211
+
212
+ return new Permissions(permissions);
213
+ }
164
214
  }
165
215
 
166
216
  module.exports = Channel;
@@ -36,6 +36,9 @@ class Guild {
36
36
 
37
37
  // Cache for guild members
38
38
  this._members = new Map();
39
+
40
+ // Initialize roles from guild data
41
+ this.roles = this.data.roles || [];
39
42
  }
40
43
 
41
44
  /**
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Represents a Discord guild member
3
3
  */
4
+ const Permissions = require("./Permissions");
5
+
4
6
  class GuildMember {
5
7
  /**
6
8
  * Create a new GuildMember instance
@@ -50,16 +52,45 @@ class GuildMember {
50
52
 
51
53
  /**
52
54
  * Get the member's permissions in this guild
53
- * @returns {Array<string>} Array of permission strings
55
+ * @returns {Permissions} Permissions bitfield
54
56
  */
55
57
  get permissions() {
56
- // This is a simplified implementation
57
- // In a full implementation, you'd calculate permissions based on roles
58
+ if (this._permissions) return this._permissions;
59
+
60
+ // Calculate permissions based on roles
61
+ let permissions = BigInt(0);
62
+
63
+ // If member is the guild owner, they have all permissions
64
+ if (this.id === this.guild.ownerId) {
65
+ permissions = Permissions.ALL;
66
+ } else {
67
+ // Start with @everyone role permissions
68
+ const everyoneRole = this.guild.roles?.find(
69
+ (role) => role.id === this.guild.id,
70
+ );
71
+ if (everyoneRole) {
72
+ permissions |= BigInt(everyoneRole.permissions || 0);
73
+ }
74
+
75
+ // Add permissions from member's roles
76
+ for (const roleId of this.roles || []) {
77
+ const role = this.guild.roles?.find((r) => r.id === roleId);
78
+ if (role) {
79
+ permissions |= BigInt(role.permissions || 0);
80
+ }
81
+ }
82
+ }
83
+
84
+ this._permissions = new Permissions(permissions);
58
85
  return this._permissions;
59
86
  }
60
87
 
61
88
  set permissions(value) {
62
- this._permissions = value ?? null;
89
+ if (value instanceof Permissions) {
90
+ this._permissions = value;
91
+ } else {
92
+ this._permissions = new Permissions(value);
93
+ }
63
94
  }
64
95
 
65
96
  /**
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+
3
+ const BitField = require("./BitField");
4
+
5
+ /**
6
+ * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
7
+ * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
8
+ * that override their default permissions.
9
+ * @extends {BitField}
10
+ */
11
+ class Permissions extends BitField {
12
+ /**
13
+ * Bitfield of the packed bits
14
+ * @type {bigint}
15
+ * @name Permissions#bitfield
16
+ */
17
+
18
+ /**
19
+ * Data that can be resolved to give a permission number. This can be:
20
+ * * A string (see {@link Permissions.FLAGS})
21
+ * * A permission number
22
+ * * An instance of Permissions
23
+ * * An Array of PermissionResolvable
24
+ * @typedef {string|bigint|Permissions|PermissionResolvable[]} PermissionResolvable
25
+ */
26
+
27
+ /**
28
+ * Gets all given bits that are missing from the bitfield.
29
+ * @param {BitFieldResolvable} bits Bit(s) to check for
30
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
31
+ * @returns {string[]}
32
+ */
33
+ missing(bits, checkAdmin = true) {
34
+ return checkAdmin && this.has(this.constructor.FLAGS.ADMINISTRATOR)
35
+ ? []
36
+ : super.missing(bits);
37
+ }
38
+
39
+ /**
40
+ * Checks whether the bitfield has a permission, or any of multiple permissions.
41
+ * @param {PermissionResolvable} permission Permission(s) to check for
42
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
43
+ * @returns {boolean}
44
+ */
45
+ any(permission, checkAdmin = true) {
46
+ return (
47
+ (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) ||
48
+ super.any(permission)
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Checks whether the bitfield has a permission, or multiple permissions.
54
+ * @param {PermissionResolvable} permission Permission(s) to check for
55
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
56
+ * @returns {boolean}
57
+ */
58
+ has(permission, checkAdmin = true) {
59
+ return (
60
+ (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) ||
61
+ super.has(permission)
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Gets an {@link Array} of bitfield names based on the permissions available.
67
+ * @returns {string[]}
68
+ */
69
+ toArray() {
70
+ return super.toArray(false);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Numeric permission flags. All available properties:
76
+ * * `CREATE_INSTANT_INVITE` (create invitations to the guild)
77
+ * * `KICK_MEMBERS`
78
+ * * `BAN_MEMBERS`
79
+ * * `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
80
+ * * `MANAGE_CHANNELS` (edit and reorder channels)
81
+ * * `MANAGE_GUILD` (edit the guild information, region, etc.)
82
+ * * `ADD_REACTIONS` (add new reactions to messages)
83
+ * * `VIEW_AUDIT_LOG`
84
+ * * `PRIORITY_SPEAKER`
85
+ * * `STREAM`
86
+ * * `VIEW_CHANNEL`
87
+ * * `SEND_MESSAGES`
88
+ * * `SEND_TTS_MESSAGES`
89
+ * * `MANAGE_MESSAGES` (delete messages and reactions)
90
+ * * `EMBED_LINKS` (links posted will have a preview embedded)
91
+ * * `ATTACH_FILES`
92
+ * * `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
93
+ * * `MENTION_EVERYONE`
94
+ * * `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
95
+ * * `VIEW_GUILD_INSIGHTS`
96
+ * * `CONNECT` (connect to a voice channel)
97
+ * * `SPEAK` (speak in a voice channel)
98
+ * * `MUTE_MEMBERS` (mute members across all voice channels)
99
+ * * `DEAFEN_MEMBERS` (deafen members across all voice channels)
100
+ * * `MOVE_MEMBERS` (move members between voice channels)
101
+ * * `USE_VAD` (use voice activity detection)
102
+ * * `CHANGE_NICKNAME`
103
+ * * `MANAGE_NICKNAMES` (change other members' nicknames)
104
+ * * `MANAGE_ROLES`
105
+ * * `MANAGE_WEBHOOKS`
106
+ * * `MANAGE_EMOJIS_AND_STICKERS`
107
+ * * `USE_APPLICATION_COMMANDS`
108
+ * * `REQUEST_TO_SPEAK`
109
+ * * `MANAGE_EVENTS`
110
+ * * `MANAGE_THREADS`
111
+ * * `USE_PUBLIC_THREADS` (deprecated)
112
+ * * `CREATE_PUBLIC_THREADS`
113
+ * * `USE_PRIVATE_THREADS` (deprecated)
114
+ * * `CREATE_PRIVATE_THREADS`
115
+ * * `USE_EXTERNAL_STICKERS` (use stickers from different guilds)
116
+ * * `SEND_MESSAGES_IN_THREADS`
117
+ * * `START_EMBEDDED_ACTIVITIES`
118
+ * * `MODERATE_MEMBERS`
119
+ * * `VIEW_CREATOR_MONETIZATION_ANALYTICS`
120
+ * * `USE_SOUNDBOARD`
121
+ * * `CREATE_GUILD_EXPRESSIONS`
122
+ * * `CREATE_EVENTS`
123
+ * * `USE_EXTERNAL_SOUNDS`
124
+ * * `SEND_VOICE_MESSAGES`
125
+ * * `USE_CLYDE_AI`
126
+ * * `SET_VOICE_CHANNEL_STATUS`
127
+ * * `SEND_POLLS`
128
+ * * `USE_EXTERNAL_APPS`
129
+ * @type {Object<string, bigint>}
130
+ * @see {@link https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags}
131
+ */
132
+ Permissions.FLAGS = {
133
+ CREATE_INSTANT_INVITE: 1n << 0n,
134
+ KICK_MEMBERS: 1n << 1n,
135
+ BAN_MEMBERS: 1n << 2n,
136
+ ADMINISTRATOR: 1n << 3n,
137
+ MANAGE_CHANNELS: 1n << 4n,
138
+ MANAGE_GUILD: 1n << 5n,
139
+ ADD_REACTIONS: 1n << 6n,
140
+ VIEW_AUDIT_LOG: 1n << 7n,
141
+ PRIORITY_SPEAKER: 1n << 8n,
142
+ STREAM: 1n << 9n,
143
+ VIEW_CHANNEL: 1n << 10n,
144
+ SEND_MESSAGES: 1n << 11n,
145
+ SEND_TTS_MESSAGES: 1n << 12n,
146
+ MANAGE_MESSAGES: 1n << 13n,
147
+ EMBED_LINKS: 1n << 14n,
148
+ ATTACH_FILES: 1n << 15n,
149
+ READ_MESSAGE_HISTORY: 1n << 16n,
150
+ MENTION_EVERYONE: 1n << 17n,
151
+ USE_EXTERNAL_EMOJIS: 1n << 18n,
152
+ VIEW_GUILD_INSIGHTS: 1n << 19n,
153
+ CONNECT: 1n << 20n,
154
+ SPEAK: 1n << 21n,
155
+ MUTE_MEMBERS: 1n << 22n,
156
+ DEAFEN_MEMBERS: 1n << 23n,
157
+ MOVE_MEMBERS: 1n << 24n,
158
+ USE_VAD: 1n << 25n,
159
+ CHANGE_NICKNAME: 1n << 26n,
160
+ MANAGE_NICKNAMES: 1n << 27n,
161
+ MANAGE_ROLES: 1n << 28n,
162
+ MANAGE_WEBHOOKS: 1n << 29n,
163
+ MANAGE_EMOJIS_AND_STICKERS: 1n << 30n,
164
+ USE_APPLICATION_COMMANDS: 1n << 31n,
165
+ REQUEST_TO_SPEAK: 1n << 32n,
166
+ MANAGE_EVENTS: 1n << 33n,
167
+ MANAGE_THREADS: 1n << 34n,
168
+ CREATE_PUBLIC_THREADS: 1n << 35n,
169
+ CREATE_PRIVATE_THREADS: 1n << 36n,
170
+ USE_EXTERNAL_STICKERS: 1n << 37n,
171
+ SEND_MESSAGES_IN_THREADS: 1n << 38n,
172
+ START_EMBEDDED_ACTIVITIES: 1n << 39n,
173
+ MODERATE_MEMBERS: 1n << 40n,
174
+ VIEW_CREATOR_MONETIZATION_ANALYTICS: 1n << 41n,
175
+ USE_SOUNDBOARD: 1n << 42n,
176
+ CREATE_GUILD_EXPRESSIONS: 1n << 43n,
177
+ CREATE_EVENTS: 1n << 44n,
178
+ USE_EXTERNAL_SOUNDS: 1n << 45n,
179
+ SEND_VOICE_MESSAGES: 1n << 46n,
180
+ USE_CLYDE_AI: 1n << 47n,
181
+ SET_VOICE_CHANNEL_STATUS: 1n << 48n,
182
+ SEND_POLLS: 1n << 49n,
183
+ USE_EXTERNAL_APPS: 1n << 50n,
184
+ };
185
+
186
+ /**
187
+ * Bitfield representing every permission combined
188
+ * @type {bigint}
189
+ */
190
+ Permissions.ALL = Object.values(Permissions.FLAGS).reduce(
191
+ (all, p) => all | p,
192
+ 0n,
193
+ );
194
+
195
+ /**
196
+ * Bitfield representing the default permissions for users
197
+ * @type {bigint}
198
+ */
199
+ Permissions.DEFAULT = BigInt(104324673);
200
+
201
+ /**
202
+ * Bitfield representing the permissions required for moderators of stage channels
203
+ * @type {bigint}
204
+ */
205
+ Permissions.STAGE_MODERATOR =
206
+ Permissions.FLAGS.MANAGE_CHANNELS |
207
+ Permissions.FLAGS.MUTE_MEMBERS |
208
+ Permissions.FLAGS.MOVE_MEMBERS;
209
+
210
+ Permissions.defaultBit = BigInt(0);
211
+
212
+ module.exports = Permissions;
package/src/index.js CHANGED
@@ -19,6 +19,8 @@
19
19
 
20
20
  const Client = require("./classes/Client");
21
21
  const WebhookClient = require("./connection/webhook/WebhookClient");
22
+ const Permissions = require("./classes/Permissions");
23
+ const BitField = require("./classes/BitField");
22
24
 
23
25
  /**
24
26
  * Main package exports
@@ -38,4 +40,18 @@ module.exports = {
38
40
  * @see {@link WebhookClient}
39
41
  */
40
42
  WebhookClient,
43
+
44
+ /**
45
+ * Discord permission flags and utilities
46
+ * @type {Permissions}
47
+ * @see {@link Permissions}
48
+ */
49
+ Permissions,
50
+
51
+ /**
52
+ * Base class for handling bitfields
53
+ * @type {BitField}
54
+ * @see {@link BitField}
55
+ */
56
+ BitField,
41
57
  };