import type { BiscuitRESTOptions, CDNRoutes, Routes } from '@biscuitland/rest'; import { CDN, BiscuitREST, Router } from '@biscuitland/rest'; import { Identify, When } from '@biscuitland/common'; import EventEmitter2 from 'eventemitter2'; import { MainManager, getBotIdFromToken } from '.'; import { GatewayManager, CreateGatewayManagerOptions, GatewayEvents } from '@biscuitland/ws'; import { GatewayIntentBits } from '@biscuitland/common'; import { actionHandler, Handler } from './events/handler'; export class Session extends EventEmitter2 { constructor(public options: BiscuitOptions) { super(); this.rest = this.createRest(this.options.rest); this.api = new Router(this.rest).createProxy(); this.cdn = CDN.createProxy(); this.managers = new MainManager(this); } rest: BiscuitREST; api: Routes; cdn: CDNRoutes; managers: MainManager; gateway!: When; private _applicationId?: string; private _botId?: string; override on(event: `${K}`, func: Handler[K]): this; override on(event: `${K}`, func: (...args: unknown[]) => unknown): this { const ev = super.on(event, func); // @ts-expect-error Eventemitter can sometimes return a listener return ev.emitter ? ev.emitter : ev; } override off(event: `${K}`, func: Handler[K]): this; override off(event: `${K}`, func: (...args: unknown[]) => unknown): this { return super.off(event, func); } override once(event: `${K}`, func: Handler[K]): this; override once(event: `${K}`, func: (...args: unknown[]) => unknown): this { const ev = super.on(event, func); // @ts-expect-error Eventemitter can sometimes return a listener return ev.emitter ? ev.emitter : ev; } override emit(event: `${K}`, ...params: Parameters): boolean; override emit(event: `${K}`, ...params: unknown[]): boolean { return super.emit(event, ...params); } set botId(id: string) { this._botId = id; } set applicationId(id: string) { this._applicationId = id; } get botId() { return this._botId ?? getBotIdFromToken(this.options.token); } get applicationId() { return this._applicationId ?? this.botId; } private createRest(rest: any) { if (!rest) { return new BiscuitREST({ ...this.options.defaultRestOptions, token: this.options.token }); } if (rest instanceof BiscuitREST || rest.cRest) { return rest; } throw new Error('[CORE] REST not found'); } async start() { // alias fixed `this` on handlePayload const ctx = this as Session; ctx.gateway = new GatewayManager({ token: this.options.token, intents: this.options.intents ?? 0, connection: this.options.defaultGatewayOptions?.connection ?? (await this.api.gateway.bot.get()), async handlePayload(shard, data) { const { t, d } = data; if (!(t && d)) return; actionHandler([ctx, { t, d }, shard]); }, ...this.options.defaultGatewayOptions }); ctx.once('READY', (payload) => { const { user, application } = payload; this.botId = user.id; this.applicationId = application.id; }); await ctx.gateway.spawnShards(); } } export type HandlePayload = Pick['handlePayload']; export interface BiscuitOptions { token: string; intents: number | GatewayIntentBits; rest?: BiscuitREST; defaultRestOptions?: Partial; defaultGatewayOptions?: Identify>>; }