cloudstorm 0.1.4 → 0.3.0

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.
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * Numeric websocket intents. All available properties:
4
+ * * `GUILDS`
5
+ * * `GUILD_MEMBERS`
6
+ * * `GUILD_BANS`
7
+ * * `GUILD_EMOJIS_AND_STICKERS`
8
+ * * `GUILD_INTEGRATIONS`
9
+ * * `GUILD_WEBHOOKS`
10
+ * * `GUILD_INVITES`
11
+ * * `GUILD_VOICE_STATES`
12
+ * * `GUILD_PRESENCES`
13
+ * * `GUILD_MESSAGES`
14
+ * * `GUILD_MESSAGE_REACTIONS`
15
+ * * `GUILD_MESSAGE_TYPING`
16
+ * * `DIRECT_MESSAGES`
17
+ * * `DIRECT_MESSAGE_REACTIONS`
18
+ * * `DIRECT_MESSAGE_TYPING`
19
+ * @see {@link https://discord.com/developers/docs/topics/gateway#list-of-intents}
20
+ */
21
+ const flags = {
22
+ GUILDS: 1 << 0,
23
+ GUILD_MEMBERS: 1 << 1,
24
+ GUILD_BANS: 1 << 2,
25
+ GUILD_EMOJIS_AND_STICKERS: 1 << 3,
26
+ GUILD_INTEGRATIONS: 1 << 4,
27
+ GUILD_WEBHOOKS: 1 << 5,
28
+ GUILD_INVITES: 1 << 6,
29
+ GUILD_VOICE_STATES: 1 << 7,
30
+ GUILD_PRESENCES: 1 << 8,
31
+ GUILD_MESSAGES: 1 << 9,
32
+ GUILD_MESSAGE_REACTIONS: 1 << 10,
33
+ GUILD_MESSAGE_TYPING: 1 << 11,
34
+ DIRECT_MESSAGES: 1 << 12,
35
+ DIRECT_MESSAGE_REACTIONS: 1 << 13,
36
+ DIRECT_MESSAGE_TYPING: 1 << 14,
37
+ };
38
+ /**
39
+ * Bitfield representing all privileged intents.
40
+ * @see {@link https://discord.com/developers/docs/topics/gateway#privileged-intents}
41
+ */
42
+ const privileged = flags.GUILD_MEMBERS | flags.GUILD_PRESENCES;
43
+ /**
44
+ * Bitfield representing all intents combined.
45
+ */
46
+ const all = Object.values(flags).reduce((acc, p) => acc | p, 0);
47
+ /**
48
+ * Bitfield representing all non-privileged intents.
49
+ */
50
+ const non_privileged = all & ~privileged;
51
+ /**
52
+ * Resolves bitfields to their numeric form.
53
+ * @param bit bit(s) to resolve.
54
+ */
55
+ function resolve(bit = 0) {
56
+ if (typeof bit === "number" && bit >= 0)
57
+ return bit;
58
+ if (typeof bit === "string" && flags[bit])
59
+ return flags[bit] | 0;
60
+ // @ts-ignore
61
+ if (Array.isArray(bit))
62
+ return bit.map((p) => resolve(p)).reduce((prev, p) => prev | p, 0);
63
+ throw new RangeError("BITFIELD_INVALID");
64
+ }
65
+ module.exports = {
66
+ flags,
67
+ all,
68
+ privileged,
69
+ non_privileged,
70
+ resolve
71
+ };
@@ -0,0 +1,69 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from "events";
3
+ import DiscordConnector from "./connector/DiscordConnector";
4
+ interface ShardEvents {
5
+ disconnect: [number, string, boolean];
6
+ error: [string];
7
+ ready: [boolean];
8
+ queueIdentify: [number];
9
+ }
10
+ interface Shard {
11
+ addListener<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
12
+ emit<E extends keyof ShardEvents>(event: E, ...args: ShardEvents[E]): boolean;
13
+ eventNames(): Array<keyof ShardEvents>;
14
+ listenerCount(event: keyof ShardEvents): number;
15
+ listeners(event: keyof ShardEvents): Array<(...args: Array<any>) => any>;
16
+ off<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
17
+ on<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
18
+ once<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
19
+ prependListener<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
20
+ prependOnceListener<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
21
+ rawListeners(event: keyof ShardEvents): Array<(...args: Array<any>) => any>;
22
+ removeAllListeners(event?: keyof ShardEvents): this;
23
+ removeListener<E extends keyof ShardEvents>(event: E, listener: (...args: ShardEvents[E]) => any): this;
24
+ }
25
+ /**
26
+ * Shard class, which provides a wrapper around the DiscordConnector with metadata like the id of the shard.
27
+ *
28
+ * This class is automatically instantiated by the library and is documented for reference.
29
+ */
30
+ declare class Shard extends EventEmitter {
31
+ id: number;
32
+ client: import("./Client");
33
+ ready: boolean;
34
+ connector: DiscordConnector;
35
+ /**
36
+ * Create a new Shard.
37
+ * @param id id of the shard.
38
+ * @param client Main class used for forwarding events.
39
+ */
40
+ constructor(id: number, client: import("./Client"));
41
+ /**
42
+ * Time in ms it took for Discord to ackknowledge an OP 1 HEARTBEAT.
43
+ */
44
+ get latency(): number;
45
+ /**
46
+ * Create a new connection to Discord.
47
+ */
48
+ connect(): void;
49
+ /**
50
+ * Close the current connection to Discord.
51
+ */
52
+ disconnect(): Promise<void>;
53
+ /**
54
+ * Send an OP 3 PRESENCE_UPDATE to Discord.
55
+ * @param data Data to send.
56
+ */
57
+ presenceUpdate(data: import("./Types").IPresence): Promise<void>;
58
+ /**
59
+ * Send an OP 4 VOICE_STATE_UPDATE to Discord.
60
+ * @param data Data to send
61
+ */
62
+ voiceStateUpdate(data: import("./Types").IVoiceStateUpdate): Promise<void>;
63
+ /**
64
+ * Send an OP 8 REQUEST_GUILD_MEMBERS to Discord.
65
+ * @param data Data to send.
66
+ */
67
+ requestGuildMembers(data: import("./Types").IRequestGuildMembers): Promise<void>;
68
+ }
69
+ export = Shard;
package/dist/Shard.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const events_1 = require("events");
6
+ const DiscordConnector_1 = __importDefault(require("./connector/DiscordConnector"));
7
+ const Constants_1 = require("./Constants");
8
+ /**
9
+ * Shard class, which provides a wrapper around the DiscordConnector with metadata like the id of the shard.
10
+ *
11
+ * This class is automatically instantiated by the library and is documented for reference.
12
+ */
13
+ class Shard extends events_1.EventEmitter {
14
+ /**
15
+ * Create a new Shard.
16
+ * @param id id of the shard.
17
+ * @param client Main class used for forwarding events.
18
+ */
19
+ constructor(id, client) {
20
+ super();
21
+ this.id = id;
22
+ this.client = client;
23
+ this.ready = false;
24
+ this.connector = new DiscordConnector_1.default(id, client);
25
+ this.connector.on("event", (event) => {
26
+ const newEvent = Object.assign(event, { shard_id: this.id });
27
+ this.client.emit("event", newEvent);
28
+ switch (event.op) {
29
+ case Constants_1.GATEWAY_OP_CODES.DISPATCH:
30
+ this.client.emit("dispatch", newEvent);
31
+ break;
32
+ case Constants_1.GATEWAY_OP_CODES.VOICE_STATE_UPDATE:
33
+ this.client.emit("voiceStateUpdate", newEvent);
34
+ break;
35
+ default:
36
+ break;
37
+ }
38
+ });
39
+ this.connector.on("disconnect", (...args) => {
40
+ this.ready = false;
41
+ this.emit("disconnect", ...args);
42
+ });
43
+ this.connector.on("error", (err) => {
44
+ this.emit("error", err);
45
+ });
46
+ this.connector.on("ready", (resume) => {
47
+ this.emit("ready", resume);
48
+ });
49
+ this.connector.on("queueIdentify", () => {
50
+ this.emit("queueIdentify", this.id);
51
+ });
52
+ }
53
+ /**
54
+ * Time in ms it took for Discord to ackknowledge an OP 1 HEARTBEAT.
55
+ */
56
+ get latency() {
57
+ return this.connector.latency;
58
+ }
59
+ /**
60
+ * Create a new connection to Discord.
61
+ */
62
+ connect() {
63
+ this.connector.connect();
64
+ }
65
+ /**
66
+ * Close the current connection to Discord.
67
+ */
68
+ disconnect() {
69
+ return this.connector.disconnect();
70
+ }
71
+ /**
72
+ * Send an OP 3 PRESENCE_UPDATE to Discord.
73
+ * @param data Data to send.
74
+ */
75
+ presenceUpdate(data) {
76
+ return this.connector.presenceUpdate(data);
77
+ }
78
+ /**
79
+ * Send an OP 4 VOICE_STATE_UPDATE to Discord.
80
+ * @param data Data to send
81
+ */
82
+ voiceStateUpdate(data) {
83
+ return this.connector.voiceStateUpdate(data);
84
+ }
85
+ /**
86
+ * Send an OP 8 REQUEST_GUILD_MEMBERS to Discord.
87
+ * @param data Data to send.
88
+ */
89
+ requestGuildMembers(data) {
90
+ return this.connector.requestGuildMembers(data);
91
+ }
92
+ }
93
+ module.exports = Shard;
@@ -0,0 +1,78 @@
1
+ /// <reference types="node" />
2
+ import Shard from "./Shard";
3
+ /**
4
+ * Class used for managing shards for the user.
5
+ *
6
+ * This class is automatically instantiated by the library and is documented for reference.
7
+ */
8
+ declare class ShardManager {
9
+ client: import("./Client");
10
+ options: import("./Client")["options"];
11
+ shards: {
12
+ [id: number]: Shard;
13
+ };
14
+ connectQueue: Array<{
15
+ action: string;
16
+ shard: Shard;
17
+ }>;
18
+ lastConnectionAttempt: number | null;
19
+ connectQueueInterval: NodeJS.Timeout;
20
+ /**
21
+ * Create a new ShardManager.
22
+ */
23
+ constructor(client: import("./Client"));
24
+ /**
25
+ * Create shard instances and add them to the connection queue.
26
+ */
27
+ spawn(): void;
28
+ /**
29
+ * Disconnect all shards facilitated by this manager.
30
+ */
31
+ disconnect(): void;
32
+ /**
33
+ * Actually connect/re-identify a single shard spawned by this manager by calling it's connect() or identify() method and reset the connection timer.
34
+ * @param data Object with a shard and action key.
35
+ */
36
+ private _connectShard;
37
+ /**
38
+ * Check if there are shards that have been spawned by this manager that are not connected yet and connect them if over 6 seconds have passed since the last attempt.
39
+ */
40
+ private _checkQueue;
41
+ /**
42
+ * Add event listeners to a shard to that the manager can act on received events.
43
+ * @param shard Shard to add the event listeners to.
44
+ */
45
+ private _addListener;
46
+ /**
47
+ * Checks if all shards spawned by this manager are ready.
48
+ */
49
+ private _checkReady;
50
+ /**
51
+ * Checks if all shards spawned by this manager are disconnected.
52
+ */
53
+ private _checkDisconnect;
54
+ /**
55
+ * Update the status of all currently connected shards which have been spawned by this manager.
56
+ * @param data Data to send.
57
+ */
58
+ presenceUpdate(data?: import("./Types").IPresence): Promise<void>;
59
+ /**
60
+ * Update the status of a single connected shard which has been spawned by this manager.
61
+ * @param shardId id of the shard.
62
+ * @param data Data to send.
63
+ */
64
+ shardPresenceUpdate(shardId: number, data?: import("./Types").IPresence): Promise<void>;
65
+ /**
66
+ * Send an OP 4 VOICE_STATE_UPDATE with a certain shard.
67
+ * @param shardId id of the shard.
68
+ * @param data Data to send.
69
+ */
70
+ voiceStateUpdate(shardId: number, data: import("./Types").IVoiceStateUpdate): Promise<void>;
71
+ /**
72
+ * Send an OP 8 REQUEST_GUILD_MEMBERS with a certain shard.
73
+ * @param shardId id of the shard.
74
+ * @param data Data to send.
75
+ */
76
+ requestGuildMembers(shardId: number, data: import("./Types").IRequestGuildMembers): Promise<void>;
77
+ }
78
+ export = ShardManager;
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const Shard_1 = __importDefault(require("./Shard"));
6
+ /**
7
+ * Class used for managing shards for the user.
8
+ *
9
+ * This class is automatically instantiated by the library and is documented for reference.
10
+ */
11
+ class ShardManager {
12
+ /**
13
+ * Create a new ShardManager.
14
+ */
15
+ constructor(client) {
16
+ this.client = client;
17
+ this.options = client.options;
18
+ if (!this.options.connectQueueInterval) {
19
+ this.options.connectQueueInterval = 1000 * 5;
20
+ }
21
+ this.shards = {};
22
+ this.connectQueue = [];
23
+ this.lastConnectionAttempt = null;
24
+ this.connectQueueInterval = setInterval(() => {
25
+ this._checkQueue();
26
+ }, this.options.connectQueueInterval);
27
+ }
28
+ /**
29
+ * Create shard instances and add them to the connection queue.
30
+ */
31
+ spawn() {
32
+ const firstShardID = this.options.firstShardId ? this.options.firstShardId : 0;
33
+ const lastShardId = this.options.lastShardId ? this.options.lastShardId : 0;
34
+ for (let i = firstShardID; i < lastShardId + 1; i++) {
35
+ this.client.emit("debug", `Spawned shard ${i}`);
36
+ this.shards[i] = new Shard_1.default(i, this.client);
37
+ this.connectQueue.push({ action: "connect", shard: this.shards[i] });
38
+ this._addListener(this.shards[i]);
39
+ }
40
+ }
41
+ /**
42
+ * Disconnect all shards facilitated by this manager.
43
+ */
44
+ disconnect() {
45
+ for (const shardKey in this.shards) {
46
+ if (this.shards[shardKey]) {
47
+ const shard = this.shards[shardKey];
48
+ shard.disconnect();
49
+ }
50
+ }
51
+ }
52
+ /**
53
+ * Actually connect/re-identify a single shard spawned by this manager by calling it's connect() or identify() method and reset the connection timer.
54
+ * @param data Object with a shard and action key.
55
+ */
56
+ _connectShard(data) {
57
+ const { action, shard } = data;
58
+ this.client.emit("debug", `${action === "connect" ? "Connecting" : "Identifying"} Shard ${shard.id} Status: ${shard.connector.status} Ready: ${shard.ready}`);
59
+ if ((this.lastConnectionAttempt || 0) <= Date.now() - 6000) {
60
+ if (action === "identify") {
61
+ this.lastConnectionAttempt = Date.now();
62
+ shard.connector.identify(true);
63
+ }
64
+ else {
65
+ if (shard.connector.status !== "connecting" && !shard.ready) {
66
+ this.lastConnectionAttempt = Date.now();
67
+ shard.connect();
68
+ }
69
+ }
70
+ }
71
+ }
72
+ /**
73
+ * Check if there are shards that have been spawned by this manager that are not connected yet and connect them if over 6 seconds have passed since the last attempt.
74
+ */
75
+ _checkQueue() {
76
+ // this.client.emit("debug", `Checking queue Length: ${this.connectQueue.length} LastAttempt: ${this.lastConnectionAttempt} Current Time: ${Date.now()}`);
77
+ if (this.connectQueue.length > 0 && ((this.lastConnectionAttempt || 0) <= Date.now() - 6000)) {
78
+ const toConnect = this.connectQueue.splice(0, 1);
79
+ for (const shard of toConnect) {
80
+ this._connectShard(shard);
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * Add event listeners to a shard to that the manager can act on received events.
86
+ * @param shard Shard to add the event listeners to.
87
+ */
88
+ _addListener(shard) {
89
+ shard.on("ready", (resume) => {
90
+ this.shards[shard.id].ready = true;
91
+ this.client.emit("debug", `Shard ${shard.id} ${resume ? "has resumed" : "is ready"}`);
92
+ this.client.emit("shardReady", { id: shard.id, ready: !resume });
93
+ this._checkReady();
94
+ });
95
+ shard.on("error", (error) => {
96
+ this.client.emit("error", error);
97
+ });
98
+ shard.on("disconnect", (code, reason, gracefulClose) => {
99
+ this.client.emit("debug", `Websocket of shard ${shard.id} closed with code ${code} and reason: ${reason ? reason : "None"}`);
100
+ if (code === 1000 && gracefulClose) {
101
+ this._checkDisconnect();
102
+ return;
103
+ }
104
+ this.connectQueue.push({ action: "connect", shard });
105
+ });
106
+ shard.on("queueIdentify", (shardId) => {
107
+ if (!this.shards[shardId]) {
108
+ this.client.emit("debug", `Received a queueIdentify event for not existing shard ${shardId}`);
109
+ return;
110
+ }
111
+ this.connectQueue.unshift({ action: "identify", shard: this.shards[shardId] });
112
+ });
113
+ }
114
+ /**
115
+ * Checks if all shards spawned by this manager are ready.
116
+ */
117
+ _checkReady() {
118
+ for (const shardId in this.shards) {
119
+ if (this.shards[shardId]) {
120
+ if (!this.shards[shardId].ready) {
121
+ return;
122
+ }
123
+ }
124
+ }
125
+ this.client.emit("ready");
126
+ }
127
+ /**
128
+ * Checks if all shards spawned by this manager are disconnected.
129
+ */
130
+ _checkDisconnect() {
131
+ for (const shardId in this.shards) {
132
+ if (this.shards[shardId]) {
133
+ if (this.shards[shardId].connector.status !== "disconnected") {
134
+ return;
135
+ }
136
+ }
137
+ }
138
+ this.client.emit("disconnected");
139
+ }
140
+ /**
141
+ * Update the status of all currently connected shards which have been spawned by this manager.
142
+ * @param data Data to send.
143
+ */
144
+ async presenceUpdate(data = {}) {
145
+ for (const shardKey in this.shards) {
146
+ if (this.shards[shardKey]) {
147
+ const shard = this.shards[shardKey];
148
+ this.shardPresenceUpdate(shard.id, data);
149
+ }
150
+ }
151
+ }
152
+ /**
153
+ * Update the status of a single connected shard which has been spawned by this manager.
154
+ * @param shardId id of the shard.
155
+ * @param data Data to send.
156
+ */
157
+ shardPresenceUpdate(shardId, data = {}) {
158
+ return new Promise((res, rej) => {
159
+ const shard = this.shards[shardId];
160
+ if (!shard) {
161
+ rej(new Error(`Shard ${shardId} does not exist`));
162
+ }
163
+ if (!shard.ready) {
164
+ shard.once("ready", () => {
165
+ shard.presenceUpdate(data).then(result => res(result)).catch(e => rej(e));
166
+ });
167
+ }
168
+ shard.presenceUpdate(data).then(result => res(result)).catch(e => rej(e));
169
+ });
170
+ }
171
+ /**
172
+ * Send an OP 4 VOICE_STATE_UPDATE with a certain shard.
173
+ * @param shardId id of the shard.
174
+ * @param data Data to send.
175
+ */
176
+ voiceStateUpdate(shardId, data) {
177
+ return new Promise((res, rej) => {
178
+ const shard = this.shards[shardId];
179
+ if (!shard) {
180
+ rej(new Error(`Shard ${shardId} does not exist`));
181
+ }
182
+ if (!shard.ready) {
183
+ shard.once("ready", () => {
184
+ shard.voiceStateUpdate(data).then(result => res(result)).catch(e => rej(e));
185
+ });
186
+ }
187
+ shard.voiceStateUpdate(data).then(result => res(result)).catch(e => rej(e));
188
+ });
189
+ }
190
+ /**
191
+ * Send an OP 8 REQUEST_GUILD_MEMBERS with a certain shard.
192
+ * @param shardId id of the shard.
193
+ * @param data Data to send.
194
+ */
195
+ requestGuildMembers(shardId, data) {
196
+ return new Promise((res, rej) => {
197
+ const shard = this.shards[shardId];
198
+ if (!shard) {
199
+ rej(new Error(`Shard ${shardId} does not exist`));
200
+ }
201
+ if (!shard.ready) {
202
+ shard.once("ready", () => {
203
+ shard.requestGuildMembers(data).then(result => res(result)).catch(e => rej(e));
204
+ });
205
+ }
206
+ shard.requestGuildMembers(data).then(result => res(result)).catch(e => rej(e));
207
+ });
208
+ }
209
+ }
210
+ module.exports = ShardManager;
@@ -0,0 +1,65 @@
1
+ import Constants from "./Constants";
2
+ export interface IntentFlags {
3
+ GUILDS: number;
4
+ GUILD_MEMBERS: number;
5
+ GUILD_BANS: number;
6
+ GUILD_EMOJIS_AND_STICKERS: number;
7
+ GUILD_INTEGRATIONS: number;
8
+ GUILD_WEBHOOKS: number;
9
+ GUILD_INVITES: number;
10
+ GUILD_VOICE_STATES: number;
11
+ GUILD_PRESENCES: number;
12
+ GUILD_MESSAGES: number;
13
+ GUILD_MESSAGE_REACTIONS: number;
14
+ GUILD_MESSAGE_TYPING: number;
15
+ DIRECT_MESSAGES: number;
16
+ DIRECT_MESSAGE_REACTIONS: number;
17
+ DIRECT_MESSAGE_TYPING: number;
18
+ }
19
+ export declare type IntentResolvable = number | Array<number> | keyof IntentFlags | Array<keyof IntentFlags>;
20
+ export interface IWSMessage {
21
+ op: typeof Constants["GATEWAY_OP_CODES"][keyof typeof Constants.GATEWAY_OP_CODES];
22
+ d?: any;
23
+ s?: number;
24
+ t?: string;
25
+ }
26
+ export interface IGatewayMessage extends IWSMessage {
27
+ shard_id: number;
28
+ }
29
+ export interface IPresenceActivity {
30
+ name: string;
31
+ type?: 0 | 1 | 2 | 3 | 5;
32
+ url?: string;
33
+ }
34
+ export interface IPresence {
35
+ status?: "online" | "idle" | "dnd" | "offline";
36
+ afk?: boolean;
37
+ since?: boolean;
38
+ activities?: Array<IPresenceActivity> | null;
39
+ }
40
+ export interface IClientOptions {
41
+ largeGuildThreshold?: number;
42
+ firstShardId?: number;
43
+ lastShardId?: number;
44
+ shardAmount?: number;
45
+ reconnect?: boolean;
46
+ initialPresence?: IPresence;
47
+ intents?: IntentResolvable;
48
+ connectQueueInterval?: number;
49
+ snowtransferInstance?: import("snowtransfer").SnowTransfer;
50
+ }
51
+ export interface IVoiceStateUpdate {
52
+ guild_id: string;
53
+ channel_id?: string | null;
54
+ self_mute?: boolean;
55
+ self_deaf?: boolean;
56
+ }
57
+ export interface IRequestGuildMembers {
58
+ guild_id: string;
59
+ query?: string | null;
60
+ limit?: number;
61
+ }
62
+ export interface IShardReady {
63
+ id: number;
64
+ ready: boolean;
65
+ }
package/dist/Types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });