seyfert 5.2.1-dev-39592791825.0 → 5.2.1
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/README.md +9 -5
- package/lib/api/utils/constants.d.ts +1 -1
- package/lib/api/utils/constants.js +1 -1
- package/lib/client/client.js +2 -2
- package/lib/client/workerclient.js +2 -2
- package/lib/langs/handler.d.ts +5 -1
- package/lib/langs/handler.js +14 -1
- package/lib/websocket/constants/index.js +1 -1
- package/lib/websocket/discord/heartbeater.js +4 -2
- package/lib/websocket/discord/shard.d.ts +1 -0
- package/lib/websocket/discord/shard.js +20 -17
- package/lib/websocket/discord/sharder.d.ts +2 -1
- package/lib/websocket/discord/sharder.js +3 -4
- package/lib/websocket/discord/socket/custom.js +11 -6
- package/lib/websocket/structures/index.js +2 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
<div align='center'>
|
|
2
2
|
<img src="./assets/icon.png" alt="seyfert" width="200px" />
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
**Seyfert is a brand-new Discord framework to take the bot development to a next level**
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
[](https://github.com/tiramisulabs/seyfert/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/seyfert)
|
|
8
|
+
[](https://discord.com/invite/XNw2RZFzaP)
|
|
9
9
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
12
12
|
## FAQ
|
|
13
|
+
|
|
13
14
|
### So, what is `seyfert`?
|
|
15
|
+
|
|
14
16
|
Seyfert is the ultimate Discord framework! We make it easy to interact with the Discord API, big cache control, scalable code and a pretty dev experience.
|
|
15
17
|
|
|
16
18
|
### Why should I use it?
|
|
17
|
-
There are many reasons to use Seyfert, but they dont all fit in this tiny readme, so here is a list of the most awesome reasons!
|
|
18
19
|
|
|
20
|
+
There are many reasons to use Seyfert, but they dont all fit in this tiny readme, so here is a list of the most awesome reasons!
|
|
19
21
|
- **Low RAM Usage**
|
|
20
22
|
- **Latest features**
|
|
21
23
|
- **Dev experience**
|
|
@@ -26,6 +28,7 @@ There are many reasons to use Seyfert, but they dont all fit in this tiny readme
|
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
## Installation
|
|
31
|
+
|
|
29
32
|
> [!NOTE]
|
|
30
33
|
> Node v18>= (or v16 with `--experimental-fetch` flag), Deno v2.6.9>= is required.
|
|
31
34
|
> Bun/Node/Deno LTS recommended.
|
|
@@ -48,6 +51,7 @@ npm i seyfert
|
|
|
48
51
|
> Or other package manager.
|
|
49
52
|
|
|
50
53
|
## Contributing
|
|
54
|
+
|
|
51
55
|
We are open to contributions, fork the repo and make your changes!
|
|
52
56
|
|
|
53
57
|
## Useful links
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const DefaultUserAgent: "DiscordBot (https://seyfert.dev, v5.2.
|
|
1
|
+
export declare const DefaultUserAgent: "DiscordBot (https://seyfert.dev, v5.2.1)";
|
|
2
2
|
export declare const ALLOWED_EXTENSIONS: readonly ["webp", "png", "jpg", "jpeg", "gif"];
|
|
3
3
|
export declare const ALLOWED_STICKER_EXTENSIONS: readonly ["png", "json", "gif"];
|
|
4
4
|
export declare const ALLOWED_SIZES: readonly [16, 32, 64, 100, 128, 256, 512, 1024, 2048, 4096];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ALLOWED_TAG_BADGE_EXTENSIONS = exports.ALLOWED_SOUNDS_EXTENSIONS = exports.ALLOWED_SIZES = exports.ALLOWED_STICKER_EXTENSIONS = exports.ALLOWED_EXTENSIONS = exports.DefaultUserAgent = void 0;
|
|
4
|
-
exports.DefaultUserAgent = 'DiscordBot (https://seyfert.dev, v5.2.
|
|
4
|
+
exports.DefaultUserAgent = 'DiscordBot (https://seyfert.dev, v5.2.1)';
|
|
5
5
|
exports.ALLOWED_EXTENSIONS = ['webp', 'png', 'jpg', 'jpeg', 'gif'];
|
|
6
6
|
exports.ALLOWED_STICKER_EXTENSIONS = ['png', 'json', 'gif'];
|
|
7
7
|
exports.ALLOWED_SIZES = [16, 32, 64, 100, 128, 256, 512, 1_024, 2_048, 4_096];
|
package/lib/client/client.js
CHANGED
|
@@ -147,10 +147,10 @@ class ClientBase extends base_1.BaseClient {
|
|
|
147
147
|
if (pluginPacket === null)
|
|
148
148
|
return null;
|
|
149
149
|
packet = pluginPacket;
|
|
150
|
-
Promise.allSettled([
|
|
150
|
+
void Promise.allSettled([
|
|
151
151
|
this.events.runEvent('RAW', this, packet, shardId, false),
|
|
152
152
|
this.collectors.run('RAW', packet, this),
|
|
153
|
-
]);
|
|
153
|
+
]);
|
|
154
154
|
switch (packet.t) {
|
|
155
155
|
case 'GUILD_MEMBER_UPDATE':
|
|
156
156
|
{
|
|
@@ -515,10 +515,10 @@ class WorkerClient extends base_1.BaseClient {
|
|
|
515
515
|
if (pluginPacket === null)
|
|
516
516
|
return null;
|
|
517
517
|
packet = pluginPacket;
|
|
518
|
-
Promise.allSettled([
|
|
518
|
+
void Promise.allSettled([
|
|
519
519
|
this.events.runEvent('RAW', this, packet, shardId, false),
|
|
520
520
|
this.collectors.run('RAW', packet, this),
|
|
521
|
-
]);
|
|
521
|
+
]);
|
|
522
522
|
switch (packet.t) {
|
|
523
523
|
case 'GUILD_MEMBER_UPDATE':
|
|
524
524
|
{
|
package/lib/langs/handler.d.ts
CHANGED
|
@@ -19,7 +19,11 @@ export declare class LangsHandler extends BaseHandler {
|
|
|
19
19
|
load(dir: string): Promise<void>;
|
|
20
20
|
parse(file: LangInstance): void | Promise<void>;
|
|
21
21
|
private applyParsedFile;
|
|
22
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Applies files synchronously until an onFile hook returns a promise.
|
|
24
|
+
* The returned promise covers the remaining files in order and rejects on the first failure.
|
|
25
|
+
*/
|
|
26
|
+
set(instances: LangInstance[]): void | Promise<void>;
|
|
23
27
|
reload(lang: string): Promise<any>;
|
|
24
28
|
reloadAll(stopIfFail?: boolean): Promise<void>;
|
|
25
29
|
onFile(locale: string, { file, name, path }: LangInstance): Awaitable<LangFileResult>;
|
package/lib/langs/handler.js
CHANGED
|
@@ -55,10 +55,23 @@ class LangsHandler extends common_1.BaseHandler {
|
|
|
55
55
|
this.__paths[result.locale] = file.path;
|
|
56
56
|
this.values[result.locale] = result.file;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Applies files synchronously until an onFile hook returns a promise.
|
|
60
|
+
* The returned promise covers the remaining files in order and rejects on the first failure.
|
|
61
|
+
*/
|
|
58
62
|
set(instances) {
|
|
63
|
+
let pending;
|
|
59
64
|
for (const i of instances) {
|
|
60
|
-
|
|
65
|
+
if (pending) {
|
|
66
|
+
pending = pending.then(() => this.parse(i));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const parsed = this.parse(i);
|
|
70
|
+
if (parsed)
|
|
71
|
+
pending = parsed;
|
|
72
|
+
}
|
|
61
73
|
}
|
|
74
|
+
return pending;
|
|
62
75
|
}
|
|
63
76
|
async reload(lang) {
|
|
64
77
|
if ((0, common_1.isCloudflareWorker)()) {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.WorkerManagerDefaults = exports.ShardManagerDefaults = exports.properties = exports.COMPRESS = void 0;
|
|
4
4
|
const COMPRESS = false;
|
|
5
5
|
exports.COMPRESS = COMPRESS;
|
|
6
|
-
const propertiesVersion = 'Seyfert v5.2.
|
|
6
|
+
const propertiesVersion = 'Seyfert v5.2.1 (https://seyfert.dev)';
|
|
7
7
|
const properties = {
|
|
8
8
|
os: process.platform,
|
|
9
9
|
browser: propertiesVersion,
|
|
@@ -16,13 +16,15 @@ class Heartbeater {
|
|
|
16
16
|
this.store.set(workerId, {
|
|
17
17
|
ack: true,
|
|
18
18
|
interval: setInterval(() => {
|
|
19
|
+
// WorkerManager callbacks observe and report their own transport/replacement failures.
|
|
19
20
|
const heartbeat = this.store.get(workerId);
|
|
20
21
|
if (!heartbeat.ack) {
|
|
21
22
|
heartbeat.ack = true;
|
|
22
|
-
|
|
23
|
+
void recreate(workerId);
|
|
24
|
+
return;
|
|
23
25
|
}
|
|
24
26
|
heartbeat.ack = false;
|
|
25
|
-
this.sendMethod(workerId, { type: 'HEARTBEAT' });
|
|
27
|
+
void this.sendMethod(workerId, { type: 'HEARTBEAT' });
|
|
26
28
|
}, this.interval),
|
|
27
29
|
});
|
|
28
30
|
}
|
|
@@ -440,16 +440,7 @@ class Shard {
|
|
|
440
440
|
this.options.handlePayload(this.id, packet);
|
|
441
441
|
return;
|
|
442
442
|
}
|
|
443
|
-
|
|
444
|
-
void (0, common_1.delay)((retry_after + 0.5) * 1e3).then(() => {
|
|
445
|
-
this.send(false, {
|
|
446
|
-
op: types_1.GatewayOpcodes.RequestGuildMembers,
|
|
447
|
-
d: {
|
|
448
|
-
...guildMemberChunk.options,
|
|
449
|
-
nonce,
|
|
450
|
-
},
|
|
451
|
-
});
|
|
452
|
-
});
|
|
443
|
+
void (0, common_1.delay)((retry_after + 0.5) * 1e3).then(() => this.sendGuildMemberRequest(nonce));
|
|
453
444
|
}
|
|
454
445
|
break;
|
|
455
446
|
}
|
|
@@ -492,15 +483,27 @@ class Shard {
|
|
|
492
483
|
timeout,
|
|
493
484
|
options,
|
|
494
485
|
});
|
|
495
|
-
this.
|
|
496
|
-
op: types_1.GatewayOpcodes.RequestGuildMembers,
|
|
497
|
-
d: {
|
|
498
|
-
...options,
|
|
499
|
-
nonce,
|
|
500
|
-
},
|
|
501
|
-
});
|
|
486
|
+
void this.sendGuildMemberRequest(nonce);
|
|
502
487
|
return promise;
|
|
503
488
|
}
|
|
489
|
+
async sendGuildMemberRequest(nonce) {
|
|
490
|
+
const chunk = this.requestGuildMembersChunk.get(nonce);
|
|
491
|
+
if (!chunk)
|
|
492
|
+
return;
|
|
493
|
+
try {
|
|
494
|
+
await this.send(false, {
|
|
495
|
+
op: types_1.GatewayOpcodes.RequestGuildMembers,
|
|
496
|
+
d: { ...chunk.options, nonce },
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
catch (error) {
|
|
500
|
+
if (this.requestGuildMembersChunk.get(nonce) !== chunk)
|
|
501
|
+
return;
|
|
502
|
+
clearTimeout(chunk.timeout);
|
|
503
|
+
this.requestGuildMembersChunk.delete(nonce);
|
|
504
|
+
chunk.reject(error);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
504
507
|
isExpectedLocalClose(code) {
|
|
505
508
|
return (code === shared_1.ShardSocketCloseCodes.Shutdown ||
|
|
506
509
|
code === shared_1.ShardSocketCloseCodes.Reconnect ||
|
|
@@ -25,7 +25,8 @@ export declare class ShardManager extends Map<number, Shard> {
|
|
|
25
25
|
disconnect(shardId: number, code?: ShardSocketCloseCodes): void | undefined;
|
|
26
26
|
disconnectAll(code?: ShardSocketCloseCodes): void;
|
|
27
27
|
setShardPresence(shardId: number, payload: GatewayUpdatePresence['d']): Promise<boolean>;
|
|
28
|
-
|
|
28
|
+
/** Waits for all presence sends, rejecting if any shard fails. */
|
|
29
|
+
setPresence(payload: GatewayUpdatePresence['d']): Promise<void>;
|
|
29
30
|
joinVoice(guild_id: string, channel_id: string, options: Pick<GatewayVoiceStateUpdate['d'], 'self_deaf' | 'self_mute'>): Promise<boolean>;
|
|
30
31
|
leaveVoice(guild_id: string): Promise<boolean>;
|
|
31
32
|
requestChannelInfo(guild_id: string, fields: ('status' | 'voice_start_time')[]): Promise<boolean>;
|
|
@@ -189,10 +189,9 @@ class ShardManager extends Map {
|
|
|
189
189
|
d: payload,
|
|
190
190
|
});
|
|
191
191
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}, this);
|
|
192
|
+
/** Waits for all presence sends, rejecting if any shard fails. */
|
|
193
|
+
async setPresence(payload) {
|
|
194
|
+
await Promise.all([...this.values()].map(shard => this.setShardPresence(shard.id, payload)));
|
|
196
195
|
}
|
|
197
196
|
joinVoice(guild_id, channel_id, options) {
|
|
198
197
|
const shardId = this.calculateShardId(guild_id);
|
|
@@ -20,7 +20,13 @@ class SeyfertWebSocket {
|
|
|
20
20
|
const urlParts = new URL(url);
|
|
21
21
|
this.hostname = urlParts.hostname || '';
|
|
22
22
|
this.path = `${urlParts.pathname}${urlParts.search || ''}`;
|
|
23
|
-
this.connect()
|
|
23
|
+
void this.connect().catch(error => {
|
|
24
|
+
if (this.__closeCalled)
|
|
25
|
+
return;
|
|
26
|
+
this.onerror(error);
|
|
27
|
+
this.__lastError = { code: 1006, reason: error instanceof Error ? error.message : String(error) };
|
|
28
|
+
this.#emitClose(this.__lastError);
|
|
29
|
+
});
|
|
24
30
|
}
|
|
25
31
|
connect(retries = 0) {
|
|
26
32
|
return new Promise((resolve, rej) => {
|
|
@@ -49,11 +55,10 @@ class SeyfertWebSocket {
|
|
|
49
55
|
const hash = (0, node_crypto_1.createHash)('sha1').update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`).digest('base64');
|
|
50
56
|
const accept = res.headers['sec-websocket-accept'];
|
|
51
57
|
if (accept !== hash) {
|
|
52
|
-
socket.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
58
|
+
socket.destroy();
|
|
59
|
+
rej(new common_1.SeyfertError('INVALID_SEC_WEBSOCKET_ACCEPT_HEADER', {
|
|
60
|
+
metadata: { detail: 'Invalid sec-websocket-accept header' },
|
|
61
|
+
}));
|
|
57
62
|
return;
|
|
58
63
|
}
|
|
59
64
|
this.socket = socket;
|
|
@@ -62,7 +62,8 @@ class DynamicBucket {
|
|
|
62
62
|
acquire(force = false) {
|
|
63
63
|
return new Promise(res => {
|
|
64
64
|
this.queue[force ? 'unshift' : 'push'](res);
|
|
65
|
-
|
|
65
|
+
// Each acquisition resolves with its permit, without waiting for the whole queue to drain.
|
|
66
|
+
void this.processQueue();
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
static chunk(array, chunks) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seyfert",
|
|
3
|
-
"version": "5.2.1
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "The most advanced framework for discord bots",
|
|
5
5
|
"packageManager": "pnpm@11.11.0",
|
|
6
6
|
"workspaces": [
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
"lint": "biome lint --write ./src",
|
|
22
22
|
"format": "biome format --write ./src",
|
|
23
23
|
"check-h": "biome check --write ./src",
|
|
24
|
-
"check": "biome check --verbose --no-errors-on-unmatched
|
|
25
|
-
"check:write": "biome check --verbose --write --no-errors-on-unmatched
|
|
24
|
+
"check": "biome check --verbose --no-errors-on-unmatched .",
|
|
25
|
+
"check:write": "biome check --verbose --write --no-errors-on-unmatched .",
|
|
26
26
|
"test:types": "pnpm run build && tsc --noEmit --project tests/tsconfig.json",
|
|
27
27
|
"test": "pnpm run test:types && vitest run --config ./tests/vitest.config.mts ./tests/"
|
|
28
28
|
},
|
|
29
29
|
"author": "MARCROCK22",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@biomejs/biome": "2.
|
|
32
|
+
"@biomejs/biome": "2.6.2",
|
|
33
33
|
"@changesets/cli": "^2.31.0",
|
|
34
34
|
"@commitlint/cli": "^21.2.1",
|
|
35
35
|
"@commitlint/config-conventional": "^21.2.0",
|