mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 18:43:31 +01:00
feat: @discordjs/ws (#8260)
Co-authored-by: Parbez <imranbarbhuiya.fsd@gmail.com>
This commit is contained in:
29
packages/ws/src/utils/IdentifyThrottler.ts
Normal file
29
packages/ws/src/utils/IdentifyThrottler.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { setTimeout as sleep } from 'node:timers/promises';
|
||||
import type { WebSocketManager } from '../ws/WebSocketManager';
|
||||
|
||||
export class IdentifyThrottler {
|
||||
private identifyState = {
|
||||
remaining: 0,
|
||||
resetsAt: Infinity,
|
||||
};
|
||||
|
||||
public constructor(private readonly manager: WebSocketManager) {}
|
||||
|
||||
public async waitForIdentify(): Promise<void> {
|
||||
if (this.identifyState.remaining <= 0) {
|
||||
const diff = this.identifyState.resetsAt - Date.now();
|
||||
if (diff <= 5_000) {
|
||||
const time = diff + Math.random() * 1_500;
|
||||
await sleep(time);
|
||||
}
|
||||
|
||||
const info = await this.manager.fetchGatewayInformation();
|
||||
this.identifyState = {
|
||||
remaining: info.session_start_limit.max_concurrency,
|
||||
resetsAt: Date.now() + 5_000,
|
||||
};
|
||||
}
|
||||
|
||||
this.identifyState.remaining--;
|
||||
}
|
||||
}
|
||||
68
packages/ws/src/utils/constants.ts
Normal file
68
packages/ws/src/utils/constants.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { Collection } from '@discordjs/collection';
|
||||
import { APIVersion, GatewayOpcodes } from 'discord-api-types/v10';
|
||||
import { lazy } from './utils';
|
||||
import type { OptionalWebSocketManagerOptions, SessionInfo } from '../ws/WebSocketManager';
|
||||
|
||||
/**
|
||||
* Valid encoding types
|
||||
*/
|
||||
export enum Encoding {
|
||||
JSON = 'json',
|
||||
}
|
||||
|
||||
/**
|
||||
* Valid compression methods
|
||||
*/
|
||||
export enum CompressionMethod {
|
||||
ZlibStream = 'zlib-stream',
|
||||
}
|
||||
|
||||
const packageJson = readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf8');
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const Package = JSON.parse(packageJson);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
|
||||
export const DefaultDeviceProperty = `@discordjs/ws ${Package.version}`;
|
||||
|
||||
const getDefaultSessionStore = lazy(() => new Collection<number, SessionInfo | null>());
|
||||
|
||||
/**
|
||||
* Default options used by the manager
|
||||
*/
|
||||
export const DefaultWebSocketManagerOptions: OptionalWebSocketManagerOptions = {
|
||||
shardCount: null,
|
||||
shardIds: null,
|
||||
largeThreshold: null,
|
||||
initialPresence: null,
|
||||
identifyProperties: {
|
||||
browser: DefaultDeviceProperty,
|
||||
device: DefaultDeviceProperty,
|
||||
os: process.platform,
|
||||
},
|
||||
version: APIVersion,
|
||||
encoding: Encoding.JSON,
|
||||
compression: null,
|
||||
retrieveSessionInfo(shardId) {
|
||||
const store = getDefaultSessionStore();
|
||||
return store.get(shardId) ?? null;
|
||||
},
|
||||
updateSessionInfo(shardId: number, info: SessionInfo | null) {
|
||||
const store = getDefaultSessionStore();
|
||||
if (info) {
|
||||
store.set(shardId, info);
|
||||
} else {
|
||||
store.delete(shardId);
|
||||
}
|
||||
},
|
||||
handshakeTimeout: 30_000,
|
||||
helloTimeout: 60_000,
|
||||
readyTimeout: 15_000,
|
||||
};
|
||||
|
||||
export const ImportantGatewayOpcodes = new Set([
|
||||
GatewayOpcodes.Heartbeat,
|
||||
GatewayOpcodes.Identify,
|
||||
GatewayOpcodes.Resume,
|
||||
]);
|
||||
20
packages/ws/src/utils/utils.ts
Normal file
20
packages/ws/src/utils/utils.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { ShardRange } from '../ws/WebSocketManager';
|
||||
|
||||
export type Awaitable<T> = T | Promise<T>;
|
||||
|
||||
/**
|
||||
* Yields the numbers in the given range as an array
|
||||
* @example
|
||||
* range({ start: 3, end: 5 }); // [3, 4, 5]
|
||||
*/
|
||||
export function range({ start, end }: ShardRange): number[] {
|
||||
return Array.from({ length: end - start + 1 }, (_, i) => i + start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily evaluate a callback, storing its result
|
||||
*/
|
||||
export function lazy<T>(cb: () => T): () => T {
|
||||
let defaultValue: T;
|
||||
return () => (defaultValue ??= cb());
|
||||
}
|
||||
Reference in New Issue
Block a user