mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-01 20:46:08 +00:00
fix: temporally using ws
This commit is contained in:
parent
a337862938
commit
983043f9c3
@ -22,7 +22,8 @@
|
||||
"author": "MARCROCK22",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"magic-bytes.js": "^1.10.0"
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"ws": "^8.18.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": [
|
||||
@ -34,6 +35,7 @@
|
||||
"@commitlint/cli": "^19.3.0",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@types/node": "^20.14.11",
|
||||
"@types/ws": "^8.5.12",
|
||||
"husky": "^9.1.1",
|
||||
"lint-staged": "^15.2.7",
|
||||
"rimraf": "5.0.9",
|
||||
|
27
pnpm-lock.yaml
generated
27
pnpm-lock.yaml
generated
@ -11,6 +11,9 @@ importers:
|
||||
magic-bytes.js:
|
||||
specifier: ^1.10.0
|
||||
version: 1.10.0
|
||||
ws:
|
||||
specifier: ^8.18.0
|
||||
version: 8.18.0
|
||||
optionalDependencies:
|
||||
chokidar:
|
||||
specifier: ^3.6.0
|
||||
@ -37,6 +40,9 @@ importers:
|
||||
'@types/node':
|
||||
specifier: ^20.14.11
|
||||
version: 20.14.11
|
||||
'@types/ws':
|
||||
specifier: ^8.5.12
|
||||
version: 8.5.12
|
||||
husky:
|
||||
specifier: ^9.1.1
|
||||
version: 9.1.1
|
||||
@ -203,6 +209,9 @@ packages:
|
||||
'@types/node@20.14.11':
|
||||
resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==}
|
||||
|
||||
'@types/ws@8.5.12':
|
||||
resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==}
|
||||
|
||||
JSONStream@1.3.5:
|
||||
resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
|
||||
hasBin: true
|
||||
@ -865,6 +874,18 @@ packages:
|
||||
resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
ws@8.18.0:
|
||||
resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -1071,6 +1092,10 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 5.26.5
|
||||
|
||||
'@types/ws@8.5.12':
|
||||
dependencies:
|
||||
'@types/node': 20.14.11
|
||||
|
||||
JSONStream@1.3.5:
|
||||
dependencies:
|
||||
jsonparse: 1.3.1
|
||||
@ -1682,6 +1707,8 @@ snapshots:
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
ws@8.18.0: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yaml@2.4.5: {}
|
||||
|
@ -1,58 +1,60 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { SeyfertWebSocket } from './socket/custom';
|
||||
// import { SeyfertWebSocket } from './socket/custom';
|
||||
import { WebSocket as NodeJSWebSocket } from 'ws';
|
||||
|
||||
export class BaseSocket {
|
||||
private internal: SeyfertWebSocket | WebSocket;
|
||||
private internal: NodeJSWebSocket | WebSocket;
|
||||
|
||||
ping?: () => Promise<number>;
|
||||
|
||||
constructor(kind: 'ws' | 'bun', url: string) {
|
||||
this.internal = kind === 'ws' ? new SeyfertWebSocket(url) : new WebSocket(url);
|
||||
this.internal = kind === 'ws' ? new NodeJSWebSocket(url) : new WebSocket(url);
|
||||
// this.internal = kind === 'ws' ? new SeyfertWebSocket(url) : new WebSocket(url);
|
||||
|
||||
if (kind === 'ws') {
|
||||
const ws = this.internal as SeyfertWebSocket;
|
||||
this.ping = ws.waitPing.bind(ws);
|
||||
ws.onpong = data => {
|
||||
const promise = ws.__promises.get(data);
|
||||
if (promise) {
|
||||
ws.__promises.delete(data);
|
||||
promise?.resolve();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const ws = this.internal as WebSocket;
|
||||
this.ping = () => {
|
||||
return new Promise<number>(res => {
|
||||
const nonce = randomUUID();
|
||||
const start = performance.now();
|
||||
const listener = (data: Buffer) => {
|
||||
if (data.toString() !== nonce) return;
|
||||
//@ts-expect-error bun support
|
||||
ws.removeListener('pong', listener);
|
||||
res(performance.now() - start);
|
||||
};
|
||||
// if (kind === 'ws') {
|
||||
// const ws = this.internal as NodeJSWebSocket;
|
||||
// this.ping = ws.waitPing.bind(ws);
|
||||
// ws.onpong = data => {
|
||||
// const promise = ws.__promises.get(data);
|
||||
// if (promise) {
|
||||
// ws.__promises.delete(data);
|
||||
// promise?.resolve();
|
||||
// }
|
||||
// };
|
||||
// } else {
|
||||
const ws = this.internal as WebSocket;
|
||||
this.ping = () => {
|
||||
return new Promise<number>(res => {
|
||||
const nonce = randomUUID();
|
||||
const start = performance.now();
|
||||
const listener = (data: Buffer) => {
|
||||
if (data.toString() !== nonce) return;
|
||||
//@ts-expect-error bun support
|
||||
ws.on('pong', listener);
|
||||
//@ts-expect-error bun support
|
||||
ws.ping(nonce);
|
||||
});
|
||||
};
|
||||
}
|
||||
ws.removeListener('pong', listener);
|
||||
res(performance.now() - start);
|
||||
};
|
||||
//@ts-expect-error bun support
|
||||
ws.on('pong', listener);
|
||||
//@ts-expect-error bun support
|
||||
ws.ping(nonce);
|
||||
});
|
||||
};
|
||||
// }
|
||||
}
|
||||
|
||||
set onopen(callback: SeyfertWebSocket['onopen']) {
|
||||
set onopen(callback: NodeJSWebSocket['onopen']) {
|
||||
this.internal.onopen = callback;
|
||||
}
|
||||
|
||||
set onmessage(callback: SeyfertWebSocket['onmessage']) {
|
||||
set onmessage(callback: NodeJSWebSocket['onmessage']) {
|
||||
this.internal.onmessage = callback;
|
||||
}
|
||||
|
||||
set onclose(callback: SeyfertWebSocket['onclose']) {
|
||||
set onclose(callback: NodeJSWebSocket['onclose']) {
|
||||
this.internal.onclose = callback;
|
||||
}
|
||||
|
||||
set onerror(callback: SeyfertWebSocket['onerror']) {
|
||||
set onerror(callback: NodeJSWebSocket['onerror']) {
|
||||
this.internal.onerror = callback;
|
||||
}
|
||||
|
||||
@ -60,7 +62,8 @@ export class BaseSocket {
|
||||
return this.internal.send(data);
|
||||
}
|
||||
|
||||
close(...args: Parameters<SeyfertWebSocket['close']>) {
|
||||
close(...args: Parameters<NodeJSWebSocket['close']>) {
|
||||
//@ts-expect-error
|
||||
return this.internal.close(...args);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ export interface ShardHeart {
|
||||
export class Shard {
|
||||
debugger?: Logger;
|
||||
data: Partial<ShardData> | ShardData = {
|
||||
resumeSeq: null,
|
||||
resume_seq: null,
|
||||
};
|
||||
|
||||
websocket: BaseSocket | null = null;
|
||||
@ -95,18 +95,20 @@ export class Shard {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(this.heart.nodeInterval);
|
||||
|
||||
this.debugger?.debug(`[Shard #${this.id}] Connecting to ${this.currentGatewayURL}`);
|
||||
|
||||
// @ts-expect-error @types/bun cause erros in compile
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: /\ bun lol
|
||||
this.websocket = new BaseSocket(typeof Bun === 'undefined' ? 'ws' : 'bun', this.currentGatewayURL);
|
||||
|
||||
//@ts-expect-error
|
||||
this.websocket!.onmessage = ({ data }: { data: string | Buffer }) => {
|
||||
this.handleMessage(data);
|
||||
};
|
||||
|
||||
this.websocket!.onclose = (event: { code: number; reason: string }) => this.handleClosed(event);
|
||||
|
||||
//@ts-expect-error
|
||||
this.websocket!.onerror = (event: ErrorEvent) => this.debugger?.error(event);
|
||||
|
||||
this.websocket!.onopen = () => {
|
||||
@ -150,14 +152,14 @@ export class Shard {
|
||||
}
|
||||
|
||||
get resumable() {
|
||||
return !!(this.data.resume_gateway_url && this.data.session_id && this.data.resumeSeq !== null);
|
||||
return !!(this.data.resume_gateway_url && this.data.session_id && this.data.resume_seq !== null);
|
||||
}
|
||||
|
||||
async resume() {
|
||||
await this.send(true, {
|
||||
op: GatewayOpcodes.Resume,
|
||||
d: {
|
||||
seq: this.data.resumeSeq!,
|
||||
seq: this.data.resume_seq!,
|
||||
session_id: this.data.session_id!,
|
||||
token: `Bot ${this.options.token}`,
|
||||
},
|
||||
@ -181,7 +183,7 @@ export class Shard {
|
||||
this.websocket!.send(
|
||||
JSON.stringify({
|
||||
op: GatewayOpcodes.Heartbeat,
|
||||
d: this.data.resumeSeq ?? null,
|
||||
d: this.data.resume_seq ?? null,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -199,10 +201,10 @@ export class Shard {
|
||||
|
||||
async onpacket(packet: GatewayReceivePayload) {
|
||||
if (packet.s !== null) {
|
||||
this.data.resumeSeq = packet.s;
|
||||
this.data.resume_seq = packet.s;
|
||||
}
|
||||
|
||||
this.debugger?.debug(`[Shard #${this.id}]`, packet.t ? packet.t : GatewayOpcodes[packet.op], this.data.resumeSeq);
|
||||
this.debugger?.debug(`[Shard #${this.id}]`, packet.t ? packet.t : GatewayOpcodes[packet.op], this.data.resume_seq);
|
||||
|
||||
switch (packet.op) {
|
||||
case GatewayOpcodes.Hello:
|
||||
@ -237,7 +239,7 @@ export class Shard {
|
||||
}
|
||||
await this.resume();
|
||||
} else {
|
||||
this.data.resumeSeq = 0;
|
||||
this.data.resume_seq = 0;
|
||||
this.data.session_id = undefined;
|
||||
await this.identify();
|
||||
}
|
||||
@ -277,17 +279,22 @@ export class Shard {
|
||||
//Force disconnect, ignore
|
||||
break;
|
||||
case 1000:
|
||||
case GatewayCloseCodes.UnknownOpcode:
|
||||
case GatewayCloseCodes.InvalidSeq:
|
||||
case GatewayCloseCodes.SessionTimedOut:
|
||||
this.data.resume_seq = 0;
|
||||
this.data.session_id = undefined;
|
||||
this.data.resume_gateway_url = undefined;
|
||||
await this.reconnect();
|
||||
break;
|
||||
case 1001:
|
||||
case 1006:
|
||||
case ShardSocketCloseCodes.ZombiedConnection:
|
||||
case GatewayCloseCodes.UnknownError:
|
||||
case GatewayCloseCodes.UnknownOpcode:
|
||||
case GatewayCloseCodes.DecodeError:
|
||||
case GatewayCloseCodes.NotAuthenticated:
|
||||
case GatewayCloseCodes.AlreadyAuthenticated:
|
||||
case GatewayCloseCodes.InvalidSeq:
|
||||
case GatewayCloseCodes.RateLimited:
|
||||
case GatewayCloseCodes.SessionTimedOut:
|
||||
this.debugger?.info(`[Shard #${this.id}] Trying to reconnect`);
|
||||
await this.reconnect();
|
||||
break;
|
||||
|
@ -66,7 +66,7 @@ export interface WorkerManagerOptions extends Omit<ShardManagerOptions, 'handleP
|
||||
|
||||
export interface ShardData {
|
||||
/** resume seq to resume connections */
|
||||
resumeSeq: number | null;
|
||||
resume_seq: number | null;
|
||||
|
||||
/**
|
||||
* resume_gateway_url is the url to resume the connection
|
||||
|
@ -15,6 +15,10 @@ export class SeyfertWebSocket {
|
||||
reject: (reason?: any) => void;
|
||||
}
|
||||
>();
|
||||
__lastError: null | {
|
||||
code: number;
|
||||
reason: string;
|
||||
} = null;
|
||||
|
||||
constructor(
|
||||
url: string,
|
||||
@ -55,6 +59,10 @@ export class SeyfertWebSocket {
|
||||
this.handleReadable();
|
||||
});
|
||||
|
||||
socket.on('close', () => {
|
||||
this.handleClose();
|
||||
});
|
||||
|
||||
socket.on('error', err => {
|
||||
this.onerror(err);
|
||||
});
|
||||
@ -135,15 +143,21 @@ export class SeyfertWebSocket {
|
||||
break;
|
||||
// close
|
||||
case 0x8:
|
||||
{
|
||||
const code = body.readUInt16BE(0);
|
||||
const reason = body.subarray(2).toString();
|
||||
this.onclose({ code, reason });
|
||||
}
|
||||
this.__lastError = {
|
||||
code: body.readUInt16BE(0),
|
||||
reason: body.subarray(2).toString(),
|
||||
};
|
||||
this.socket?.destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleClose() {
|
||||
if (!this.__lastError) return this.connect();
|
||||
this.onclose(this.__lastError);
|
||||
this.__lastError = null;
|
||||
}
|
||||
|
||||
send(data: string) {
|
||||
this._write(Buffer.from(data), 1);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user