fix: socket (#253)

* fix: socket

* fix: name

* fix: use logger and debugger
This commit is contained in:
MARCROCK22 2024-08-24 02:26:09 -04:00 committed by GitHub
parent 330b840b10
commit 8c4a13264e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 76 additions and 51 deletions

View File

@ -1,5 +1,5 @@
import { inflateSync } from 'node:zlib';
import { type MakeRequired, MergeOptions, type Logger } from '../../common';
import { Logger, LogLevels, type MakeRequired, MergeOptions } from '../../common';
import { properties } from '../constants';
import { DynamicBucket } from '../structures';
import { ConnectTimeout } from '../structures/timeout';
@ -23,6 +23,7 @@ export interface ShardHeart {
}
export class Shard {
logger: Logger;
debugger?: Logger;
data: Partial<ShardData> | ShardData = {
resume_seq: null,
@ -52,6 +53,11 @@ export class Shard {
},
} as ShardOptions);
this.logger = new Logger({
name: `[Shard #${id}]`,
logLevel: LogLevels.Info,
});
if (options.debugger) this.debugger = options.debugger;
const safe = this.calculateSafeRequests();
@ -91,7 +97,7 @@ export class Shard {
async connect() {
await this.connectTimeout.wait();
if (this.isOpen) {
this.debugger?.debug(`[Shard #${this.id}] attempted to connect while open`);
this.debugger?.debug(`[Shard #${this.id}] Attempted to connect while open`);
return;
}
@ -109,7 +115,7 @@ export class Shard {
this.websocket.onclose = (event: { code: number; reason: string }) => this.handleClosed(event);
this.websocket.onerror = (event: ErrorEvent) => this.debugger?.error(event);
this.websocket.onerror = (event: ErrorEvent) => this.logger.error(event);
this.websocket.onopen = () => {
this.heart.ack = true;
@ -235,7 +241,7 @@ export class Shard {
case GatewayOpcodes.InvalidSession:
if (packet.d) {
if (!this.resumable) {
return this.debugger?.fatal(`[Shard #${this.id}] This is a completely unexpected error message.`);
return this.logger.fatal(`This is a completely unexpected error message.`);
}
await this.resume();
} else {
@ -269,8 +275,8 @@ export class Shard {
protected async handleClosed(close: { code: number; reason: string }) {
clearInterval(this.heart.nodeInterval);
this.debugger?.warn(
`[Shard #${this.id}] ${ShardSocketCloseCodes[close.code] ?? GatewayCloseCodes[close.code] ?? close.code} (${close.code})`,
this.logger.warn(
`${ShardSocketCloseCodes[close.code] ?? GatewayCloseCodes[close.code] ?? close.code} (${close.code})`,
close.reason,
);
@ -295,7 +301,7 @@ export class Shard {
case GatewayCloseCodes.NotAuthenticated:
case GatewayCloseCodes.AlreadyAuthenticated:
case GatewayCloseCodes.RateLimited:
this.debugger?.info(`[Shard #${this.id}] Trying to reconnect`);
this.logger.info(`Trying to reconnect`);
await this.reconnect();
break;
@ -305,11 +311,11 @@ export class Shard {
case GatewayCloseCodes.InvalidIntents:
case GatewayCloseCodes.InvalidShard:
case GatewayCloseCodes.ShardingRequired:
this.debugger?.fatal(`[Shard #${this.id}] cannot reconnect`);
this.logger.fatal(`Cannot reconnect`);
break;
default:
this.debugger?.warn(`[Shard #${this.id}] Unknown close code, trying to reconnect anyways`);
this.logger.warn(`Unknown close code, trying to reconnect anyways`);
await this.reconnect();
break;
}
@ -324,10 +330,17 @@ export class Shard {
}
protected handleMessage(data: string | Buffer) {
if (data instanceof Buffer) {
data = inflateSync(data);
let packet;
try {
if (data instanceof Buffer) {
data = inflateSync(data);
}
packet = JSON.parse(data as string);
} catch (e) {
this.logger.error(e);
return;
}
return this.onpacket(JSON.parse(data as string));
return this.onpacket(packet);
}
checkOffline(force: boolean) {

View File

@ -28,45 +28,57 @@ export class SeyfertWebSocket {
this.connect();
}
private connect() {
const key = randomBytes(16).toString('base64');
const req = request({
//discord gateway hostname
hostname: this.hostname,
path: this.path,
headers: {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Key': key,
'Sec-WebSocket-Version': '13',
},
private connect(retries = 0) {
return new Promise<void>((resolve, rej) => {
const key = randomBytes(16).toString('base64');
const req = request({
//discord gateway hostname
hostname: this.hostname,
path: this.path,
headers: {
Connection: 'Upgrade',
Upgrade: 'websocket',
'Sec-WebSocket-Key': key,
'Sec-WebSocket-Version': '13',
},
});
req.on('upgrade', (res, socket) => {
const hash = createHash('sha1').update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`).digest('base64');
const accept = res.headers['sec-websocket-accept'];
if (accept !== hash) {
socket.end(() => {
rej(new Error('Invalid sec-websocket-accept header'));
});
return;
}
this.socket = socket;
socket.on('readable', this.handleReadable.bind(this));
socket.on('close', this.handleClose.bind(this));
socket.on('error', err => this.onerror(err));
resolve();
this.onopen();
});
req.on('close', () => {
req.removeAllListeners();
});
req.on('error', e => {
if (retries < 5) {
setTimeout(() => {
resolve(this.connect(retries + 1));
}, 500);
} else {
rej(e);
}
});
req.end();
});
req.on('upgrade', (res, socket) => {
const hash = createHash('sha1').update(`${key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`).digest('base64');
const accept = res.headers['sec-websocket-accept'];
if (accept !== hash) {
socket.end(() => {
this.onerror(new Error('Invalid sec-websocket-accept header'));
});
return;
}
this.socket = socket;
socket.on('readable', this.handleReadable.bind(this));
socket.on('close', this.handleClose.bind(this));
socket.on('error', err => this.onerror(err));
this.onopen();
});
req.on('close', () => {
req.removeAllListeners();
});
req.end();
}
handleReadable() {
@ -148,7 +160,7 @@ export class SeyfertWebSocket {
}
}
handleClose() {
async handleClose() {
this.socket?.removeAllListeners();
this.socket?.destroy();
this.socket = undefined;