diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 1d82553..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "env": { - "es2021": true, - "node": true - }, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended" - ], - "ignorePatterns": [ - "**/dist/*" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2021, - "sourceType": "module" - }, - "plugins": [ - "@typescript-eslint", - "prettier", - "import" - ], - "rules": { - "prettier/prettier": [ - "error", - { - "tabWidth": 4, - "printWidth": 150, - "singleQuote": true, - "semi": false, - "quoteProps": "as-needed", - "trailingComma": "none", - "endOfLine": "lf", - "arrowParens": "avoid" - } - ], - "import/order": [ - "error", - { - "groups": [ - "builtin", - "external", - "internal", - "index", - "sibling", - "parent" - ], - "alphabetize": { - "order": "asc" - } - } - ], - "strict": [ - "error", - "global" - ], - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "never" - ], - "@typescript-eslint/no-non-null-assertion": "off" - } -} \ No newline at end of file diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml deleted file mode 100644 index 82f72f0..0000000 --- a/.github/workflows/documentation.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Publish Documentation -on: - push: - branches: [ stable ] -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: 16 - - - name: Install dependencies - run: yarn install - - - name: Build - run: yarn run docs - - - name: Deploy - uses: JamesIves/github-pages-deploy-action@4.1.5 - with: - branch: docs - folder: docs \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..eb15df9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,13 @@ +name: Typecheck Files + +on: [push, pull_request] + +jobs: + typecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: denoland/setup-deno@004814556e37c54a2f6e31384c9e18e983317366 + with: + deno-version: v1.x + - run: deno lint && deno fmt --check \ No newline at end of file diff --git a/.github/workflows/npm_publish.yml b/.github/workflows/npm_publish.yml new file mode 100644 index 0000000..02261d3 --- /dev/null +++ b/.github/workflows/npm_publish.yml @@ -0,0 +1,24 @@ +name: Publish Package to npmjs +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: denoland/setup-deno@004814556e37c54a2f6e31384c9e18e983317366 + with: + deno-version: v1.x + - uses: pnpm/action-setup@v2 + with: + version: 7.x.x + run_install: false + - uses: actions/setup-node@v3 + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + - run: deno run -A scripts/build_npm.ts ${{github.ref_name}} + - run: cd npm && pnpm install && pnpm publish --access=public --no-git-checks + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml deleted file mode 100644 index 3ee58e7..0000000 --- a/.github/workflows/typecheck.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Typecheck Files - -on: [push, pull_request] -jobs: - typecheck: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: 16.x - - run: yarn install - - run: yarn test diff --git a/.gitignore b/.gitignore index 317588a..1d8e50f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .env -node_modules -dist +npm test.* \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index b127ac9..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "singleQuote": true, - "printWidth": 150, - "trailingComma": "none", - "endOfLine": "lf", - "arrowParens": "avoid", - "semi": false, - "tabWidth": 4 -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..01cede9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "deno.enable": true, + "deno.lint": true, + "deno.unstable": false +} \ No newline at end of file diff --git a/README.md b/README.md index 153d08d..4b83268 100644 --- a/README.md +++ b/README.md @@ -8,20 +8,23 @@ A JS/TS library to interact with Revolt API ### Features - Built with TypeScript - Object-oriented -- Lightweight ([revolt.io *3 pkg](/package.json) > [revolt.js 12* pkg](https://github.com/revoltchat/revolt.js/blob/master/package.json)) +- Lightweight - Voice Support (*work in progress..*) -- [Deno](./deno) Support +- Deno Support -## Installation +## Installation (NodeJS Only) ***Node.js v16.x or newer is required.*** ```bash $ npm i revolt.io ``` ## Usage -```js +```ts import { Client } from 'revolt.io' +// for Deno runtime use this +// import { Client } from 'https://deno.land/x/revoltio/mod.ts' + const client = new Client() // Login with bot account @@ -44,7 +47,7 @@ client.on('message', msg => { ## Links - [More examples](/examples) -- [Documentation](https://revolt-io.github.io/revolt.io/) +- [Documentation](https://doc.deno.land/https://deno.land/x/revoltio/mod.ts) ## License Refer to the [LICENSE](LICENSE) file. diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..465e657 --- /dev/null +++ b/deno.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "strict": true + }, + "fmt": { + "files": { + "include": [ + "src", + "examples", + "scripts" + ] + }, + "options": { + "singleQuote": true + } + }, + "lint": { + "files": { + "include": [ + "src" + ] + }, + "rules": { + "tags": [ + "recommended" + ], + "include": [], + "exclude": [] + } + } +} \ No newline at end of file diff --git a/deno/README.md b/deno/README.md deleted file mode 100644 index faf4633..0000000 --- a/deno/README.md +++ /dev/null @@ -1,46 +0,0 @@ -Revolt.io [![NPM version](https://img.shields.io/npm/v/revolt.io.svg?style=flat-square&color=informational)](https://npmjs.com/package/revolt.io) -==== - - -### Overview -A JS/TS library to interact with Revolt API - -### Features -- Built with TypeScript -- Object-oriented -- Lightweight ([revolt.io *3 pkg](/package.json) > [revolt.js 12* pkg](https://github.com/revoltchat/revolt.js/blob/master/package.json)) -- Voice Support (*work in progress..*) -- [Deno](./deno) Support - - - -## Usage -```js -import { Client } from 'https://deno.land/x/revoltio/index.ts' - -const client = new Client() - -// Login with bot account -client.login('revolt-token-here') - -// Self bot -// client.login('revolt-token-here', 'user') - -client.on('ready', () => { - console.log('Connected') - console.log(client.user.username) -}) - -client.on('message', msg => { - if (msg.content === '!ping') { - msg.reply('Pong!') - } -}) -``` - -## Links -- [More examples](/examples) -- [Documentation](https://doc.deno.land/https://deno.land/x/revoltio/index.ts) - -## License -Refer to the [LICENSE](LICENSE) file. diff --git a/deno/client/BaseClient.ts b/deno/client/BaseClient.ts deleted file mode 100644 index 17f86f9..0000000 --- a/deno/client/BaseClient.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { EventEmitter } from 'https://deno.land/std@0.132.0/node/events.ts' -import { Client } from '../client/index.ts' -import { REST, Endpoints } from '../rest/index.ts' -import type { Channel, DMChannel, GroupChannel, Role, ServerMember, TextChannel, User, Server, Message } from '../structures/index.ts' -import { DEFAULT_CLIENT_OPTIONS, Events } from '../util/Constants.ts' - -export interface ClientEvents { - message: [Message] - messageDelete: [Message] - messageUpdate: [Message, Message] - ready: [Client] - serverCreate: [Server] - serverDelete: [Server] - serverUpdate: [Server, Server] - debug: [string] - error: [unknown] - raw: [unknown] - userUpdate: [User, User] - serverMemberJoin: [ServerMember] - channelUpdate: [Channel, Channel] - serverMemberLeave: [ServerMember] - serverMemberUpdate: [ServerMember, ServerMember] - roleDelete: [Role] - typingStart: [TextChannel | DMChannel | GroupChannel, User] - typingStop: [TextChannel | DMChannel | GroupChannel, User] - groupJoin: [GroupChannel, User] - groupLeave: [GroupChannel, User] -} - -export declare interface BaseClient { - on(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - on(event: Exclude, listener: (...args: any[]) => Awaited): this - once(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - once(event: Exclude, listener: (...args: any[]) => Awaited): this - emit(event: K, ...args: ClientEvents[K]): boolean - emit(event: Exclude, ...args: unknown[]): boolean - off(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - off(event: Exclude, listener: (...args: any[]) => Awaited): this - removeAllListeners(event?: K): this - removeAllListeners(event?: Exclude): this -} - -export interface BaseClientOptions { - rest: { - url: string - retries: number - timeout: number - } - endpoints: { - cdn: string - invite: string - api: string - } - ws: { - heartbeat: number - } -} - -type DeepPartial = T extends object - ? { - [P in keyof T]?: DeepPartial - } - : T - -export function isObject(item: unknown) { - return item && typeof item === 'object' && !Array.isArray(item) -} - -export abstract class BaseClient extends EventEmitter { - readonly api: REST - readonly endpoints: Endpoints - #token: string | null = null - bot = true - options = { ...DEFAULT_CLIENT_OPTIONS } - - constructor(opts: DeepPartial = {}) { - super() - - for (const key in opts) { - Object.assign(this.options[key as keyof BaseClientOptions], opts[key as keyof BaseClientOptions]) - } - - this.api = new REST(this.options.rest) - this.endpoints = new Endpoints(this.options.endpoints) - this.api.debug = (msg: string) => this.emit(Events.DEBUG, msg) - } - - set token(token: string | null) { - this.#token = token - this.api.setToken(token, this.bot) - } - - get token() { - return this.#token - } -} diff --git a/deno/client/Client.ts b/deno/client/Client.ts deleted file mode 100644 index f920c74..0000000 --- a/deno/client/Client.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { RevoltConfig } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseClient, WebSocketShard } from './index.ts' -import { ActionManager } from './actions/ActionManager.ts' -import { Error } from '../errors/index.ts' -import { ChannelManager, ServerManager, UserManager } from '../managers/index.ts' -import { ClientUser } from '../structures/index.ts' -import { Events } from '../util/Constants.ts' - -export class Client extends BaseClient { - protected readonly ws = new WebSocketShard(this) - readonly actions = new ActionManager(this) - readonly channels = new ChannelManager(this) - readonly servers = new ServerManager(this) - readonly users = new UserManager(this) - user: ClientUser | null = null - configuration?: RevoltConfig - readyAt: Date | null = null - - get readyTimestamp(): number | null { - return this.readyAt?.getTime() ?? null - } - - get uptime(): number | null { - return this.readyAt ? Date.now() - this.readyAt.getTime() : null - } - - async login(token?: string, type: 'user' | 'bot' = 'bot'): Promise { - if (!token) throw new Error('INVALID_TOKEN') - - this.debug('Fetch configuration...') - - this.configuration = await this.api.get('/') - this.bot = type.toLowerCase() === 'bot' - this.token = token ?? null - - this.debug('Preparing to connect to the gateway...') - - try { - await this.ws.connect() - } catch (err) { - await this.destroy() - throw err - } - - this.readyAt = new Date() - } - - async destroy(): Promise { - this.token = null - this.user = null - this.readyAt = null - this.api.setToken(null) - await this.ws.destroy() - } - - private debug(message: string): void { - this.emit(Events.DEBUG, message) - } - - isReady(): boolean { - return this.readyAt != null - } -} diff --git a/deno/client/WebSocket.ts b/deno/client/WebSocket.ts deleted file mode 100644 index 40e9d4e..0000000 --- a/deno/client/WebSocket.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import type { Client } from './Client.ts' -import { ClientUser } from '../structures/index.ts' -import { Events, WSEvents } from '../util/index.ts' - -export class WebSocketShard { - heartbeatInterval?: number - lastPingTimestamp?: number - lastPongAcked = false - socket: WebSocket | null = null - connected = false - ready = false - - constructor(protected readonly client: Client) {} - - send(data: unknown): Promise { - return new Promise(resolve => { - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.send(JSON.stringify(data)) - resolve() - } else { - this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`) - resolve() - } - }) - } - - private async onOpen(): Promise { - await this.send({ - type: WSEvents.AUTHENTICATE, - token: this.client.token - }) - } - - private debug(message: unknown): void { - this.client.emit(Events.DEBUG, `[WS]: ${message}`) - } - - get ping(): number { - if (!this.lastPingTimestamp) return -0 - return Date.now() - this.lastPingTimestamp - } - - setHeartbeatTimer(time: number): void { - this.debug(`Setting a heartbeat interval for ${time}ms.`) - - if (this.heartbeatInterval) clearInterval(this.heartbeatInterval) - - if (time !== -1) { - this.heartbeatInterval = setInterval(() => this.sendHeartbeat(), time) - } - } - - sendHeartbeat(skip = false): void { - if (!skip && !this.lastPongAcked) { - this.debug('Did not receive a pong ack last time.') - } - - const now = Date.now() - - this.debug('Sending a heartbeat.') - this.send({ type: WSEvents.PING, data: now }) - this.lastPongAcked = false - this.lastPingTimestamp = now - } - - private onError(event: ErrorEvent | Event): void { - this.client.emit(Events.ERROR, event) - } - - private onMessage({ data }: MessageEvent): void { - let packet: unknown - - try { - packet = JSON.parse(data as unknown as string) - } catch (err) { - this.client.emit(Events.ERROR, err) - return - } - - this.client.emit(Events.RAW, packet) - - this.onPacket(packet) - } - - private onClose(event: CloseEvent): void { - this.debug(`[WS] Closed with reason: ${event.reason}, code: ${event.code}`) - this.destroy() - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private onPacket(packet: any) { - if (!packet) { - this.debug(`Received broken packet: '${packet}'.`) - return - } - - switch (packet.type) { - case WSEvents.AUTHENTICATED: - this.connected = true - break - case WSEvents.PONG: - this.lastPongAcked = true - break - case WSEvents.ERROR: - this.client.emit(Events.ERROR, packet.error) - break - case WSEvents.READY: - this.lastPongAcked = true - - for (const user of packet.users) { - this.client.users._add(user) - if (user.relationship === 'User' && !this.client.user) { - const clientUser = (this.client.user = new ClientUser(this.client, user)) - this.client.users.cache.set(clientUser.id, clientUser) - } - } - - for (const server of packet.servers) { - this.client.servers._add(server) - } - - for (const channel of packet.channels) { - this.client.channels._add(channel) - } - - for (const member of packet.members) { - this.client.servers.cache.get(member._id.server)?.members._add(member) - } - - this.setHeartbeatTimer(this.client.options.ws.heartbeat) - - this.ready = true - - this.client.emit(Events.READY, this.client) - - break - default: { - const action = this.client.actions.get(packet.type) - - if (action) { - action.handle(packet) - } else { - this.debug(`Received unknown packet "${packet.type}"`) - } - - break - } - } - } - - connect(): Promise { - return new Promise(resolve => { - if (this.socket?.readyState === WebSocket.OPEN && this.ready) { - return resolve(this) - } - - if (typeof this.client.configuration === 'undefined') { - throw new Error('Attempted to open WebSocket without syncing configuration from server.') - } - - if (typeof this.client.token !== 'string') { - throw new Error('Attempted to open WebSocket without valid token.') - } - - const ws = (this.socket = this.socket ?? new WebSocket(this.client.configuration.ws)) - - // NOTE: Don't remove the 'any' they are requires to work with deno - ws.onopen = this.onOpen.bind(this) as any - ws.onmessage = this.onMessage.bind(this) as any - ws.onerror = this.onError.bind(this) as any - ws.onclose = this.onClose.bind(this) as any - ws.addEventListener('open', () => resolve(this)) - }) - } - - destroy(): Promise { - return new Promise(resolve => { - this.setHeartbeatTimer(-1) - this.connected = false - this.ready = false - - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.addEventListener('close', () => resolve(this)) - this.socket.close() - } else { - resolve(this) - } - }) - } -} diff --git a/deno/client/actions/Action.ts b/deno/client/actions/Action.ts deleted file mode 100644 index 1ee999f..0000000 --- a/deno/client/actions/Action.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Client } from '../Client.ts' - -export abstract class Action { - constructor(public client: Client) {} - abstract handle(data: unknown): unknown -} diff --git a/deno/client/actions/ActionManager.ts b/deno/client/actions/ActionManager.ts deleted file mode 100644 index 8108d33..0000000 --- a/deno/client/actions/ActionManager.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as Actions from './index.ts' -import { Action as BaseAction } from './Action.ts' -import { Client } from '../Client.ts' - -export class ActionManager { - private actions: Record = {} - - constructor(public client: Client) { - for (const Action of Object.values(Actions)) this.register(Action) - } - - register(Action: new (client: Client) => BaseAction): void { - this.actions[Action.name.replace(/Action$/, '')] = new Action(this.client) - } - - get(name: string): BaseAction | null { - return this.actions[name as keyof ActionManager] ?? null - } -} diff --git a/deno/client/actions/ChannelCreate.ts b/deno/client/actions/ChannelCreate.ts deleted file mode 100644 index 9edf051..0000000 --- a/deno/client/actions/ChannelCreate.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ChannelCreateAction extends Action { - async handle(data: APIChannel): Promise { - const channel = this.client.channels._add(data) - - if (channel) { - if (channel.inServer()) { - const server = channel.server ?? (await this.client.servers.fetch(channel.serverId)) - server.channels.cache.set(channel.id, channel) - } - this.client.emit(Events.CHANNEL_CREATE, channel) - } - - return { channel } - } -} diff --git a/deno/client/actions/ChannelDelete.ts b/deno/client/actions/ChannelDelete.ts deleted file mode 100644 index 70ee669..0000000 --- a/deno/client/actions/ChannelDelete.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ChannelDeleteAction extends Action { - handle(data: { id: string }): unknown { - const channel = this.client.channels.cache.get(data.id) - - if (channel) { - if (channel.inServer()) { - channel.server?.channels.cache.delete(channel.id) - } - this.client.emit(Events.CHANNEL_DELETE, channel) - } - - return { channel } - } -} diff --git a/deno/client/actions/ChannelGroupJoin.ts b/deno/client/actions/ChannelGroupJoin.ts deleted file mode 100644 index 1943bb7..0000000 --- a/deno/client/actions/ChannelGroupJoin.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ChannelGroupJoinAction extends Action { - async handle(data: { id: string; user: string }): Promise { - const channel = this.client.channels.cache.get(data.id) - const user = await this.client.users.fetch(data.user, { force: false }) - - if (channel?.isGroup()) { - channel.users.set(user.id, user) - this.client.emit(Events.GROUP_JOIN, channel, user) - } - - return { channel, user } - } -} diff --git a/deno/client/actions/ChannelGroupLeave.ts b/deno/client/actions/ChannelGroupLeave.ts deleted file mode 100644 index 0aa7342..0000000 --- a/deno/client/actions/ChannelGroupLeave.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/index.ts' - -export class ChannelGroupLeaveAction extends Action { - async handle(data: { id: string; user: string }): Promise { - const channel = this.client.channels.cache.get(data.id) - const user = await this.client.users.fetch(data.user, { force: false }) - - if (channel?.isGroup()) { - channel.users.delete(data.user) - this.client.emit(Events.GROUP_LEAVE, channel, user) - } - - return { channel, user } - } -} diff --git a/deno/client/actions/ChannelStartTyping.ts b/deno/client/actions/ChannelStartTyping.ts deleted file mode 100644 index 4ed0ccb..0000000 --- a/deno/client/actions/ChannelStartTyping.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/index.ts' - -export class ChannelStartTypingAction extends Action { - handle(data: { id: string; user: string }): unknown { - const channel = this.client.channels.cache.get(data.id) - const user = this.client.users.cache.get(data.user) - - if (channel?.isText() && user) { - this.client.emit(Events.TYPING_START, channel, user) - } - - return { channel, user } - } -} diff --git a/deno/client/actions/ChannelStopTyping.ts b/deno/client/actions/ChannelStopTyping.ts deleted file mode 100644 index baf91a9..0000000 --- a/deno/client/actions/ChannelStopTyping.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/index.ts' - -export class ChannelStopTypingAction extends Action { - handle(data: { id: string; user: string }): unknown { - const channel = this.client.channels.cache.get(data.id) - const user = this.client.users.cache.get(data.user) - - if (channel?.isText() && user) { - this.client.emit(Events.TYPING_STOP, channel, user) - } - - return { channel, user } - } -} diff --git a/deno/client/actions/ChannelUpdate.ts b/deno/client/actions/ChannelUpdate.ts deleted file mode 100644 index 7cf2836..0000000 --- a/deno/client/actions/ChannelUpdate.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ChannelUpdateAction extends Action { - handle(data: { id: string; data: APIChannel }): unknown { - const oldChannel = this.client.channels.cache.get(data.id) - - if (oldChannel) { - const newChannel = oldChannel._update(data.data) - - this.client.channels.cache.set(newChannel.id, newChannel) - this.client.emit(Events.CHANNEL_UPDATE, oldChannel, newChannel) - - return { newChannel, oldChannel } - } - - return { oldChannel } - } -} diff --git a/deno/client/actions/Message.ts b/deno/client/actions/Message.ts deleted file mode 100644 index 7a3beae..0000000 --- a/deno/client/actions/Message.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Message as APIMessage } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events, SYSTEM_USER_ID } from '../../util/Constants.ts' - -export class MessageAction extends Action { - async handle(data: APIMessage): Promise { - const channel = this.client.channels.cache.get(data.channel) - - if (channel?.isText()) { - const message = channel.messages._add(data) - - if (data.author !== SYSTEM_USER_ID) await this.client.users.fetch(data.author, { force: false }) - - this.client.emit(Events.MESSAGE, message) - - return { message } - } - - return {} - } -} diff --git a/deno/client/actions/MessageDelete.ts b/deno/client/actions/MessageDelete.ts deleted file mode 100644 index ad810ca..0000000 --- a/deno/client/actions/MessageDelete.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class MessageDeleteAction extends Action { - handle(data: { id: string; channel: string }): unknown { - const channel = this.client.channels.cache.get(data.channel) - - if (channel?.isText()) { - const message = channel.messages.cache.get(data.id) - - if (message) { - channel.messages._remove(message.id) - this.client.emit(Events.MESSAGE_DELETE, message) - } - - return { message } - } - - return {} - } -} diff --git a/deno/client/actions/MessageUpdate.ts b/deno/client/actions/MessageUpdate.ts deleted file mode 100644 index f906d05..0000000 --- a/deno/client/actions/MessageUpdate.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { Message as APIMessage } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class MessageUpdateAction extends Action { - handle(data: { id: string; channel: string; data: APIMessage }): unknown { - const channel = this.client.channels.cache.get(data.channel) - - if (!channel?.isText()) return - - const oldMessage = channel?.messages.cache.get(data.id) - - if (oldMessage) { - const newMessage = oldMessage._update(data.data) - - channel.messages.cache.set(newMessage.id, newMessage) - - this.client.emit(Events.MESSAGE_UPDATE, oldMessage, newMessage) - - return { newMessage, oldMessage } - } - - return { oldMessage } - } -} diff --git a/deno/client/actions/ServerDelete.ts b/deno/client/actions/ServerDelete.ts deleted file mode 100644 index c5baa3a..0000000 --- a/deno/client/actions/ServerDelete.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerDeleteAction extends Action { - handle(data: APIServer): unknown { - const server = this.client.servers.cache.get(data._id) - - if (server) { - this.client.servers._remove(server.id) - this.client.emit(Events.SERVER_DELETE, server) - } - - return { server } - } -} diff --git a/deno/client/actions/ServerMemberJoin.ts b/deno/client/actions/ServerMemberJoin.ts deleted file mode 100644 index 64cd0bb..0000000 --- a/deno/client/actions/ServerMemberJoin.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerMemberJoin extends Action { - async handle(data: { id: string; user: string }): Promise { - let server = this.client.servers.cache.get(data.id) - - if (!server) { - server = await this.client.servers.fetch(data.id) - this.client.emit(Events.SERVER_CREATE, server) - } - - const member = await server.members.fetch(data.user) - - server.members.cache.set(member.id, member) - - this.client.emit(Events.SERVER_MEMBER_JOIN, member) - - return { member } - } -} diff --git a/deno/client/actions/ServerMemberLeave.ts b/deno/client/actions/ServerMemberLeave.ts deleted file mode 100644 index e23305d..0000000 --- a/deno/client/actions/ServerMemberLeave.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerMemberLeaveAction extends Action { - handle(data: { id: string; user: string }): unknown { - const server = this.client.servers.cache.get(data.id) - - if (server) { - const member = server.members.cache.get(data.user) - - if (member) { - server.members._remove(member.id) - this.client.emit(Events.SERVER_MEMBER_LEAVE, member) - } - - return { server, member } - } - - return { server } - } -} diff --git a/deno/client/actions/ServerMemberUpdate.ts b/deno/client/actions/ServerMemberUpdate.ts deleted file mode 100644 index 9a873b1..0000000 --- a/deno/client/actions/ServerMemberUpdate.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Member as APIMember } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerMemberUpdateAction extends Action { - handle(data: { id: string; data: APIMember }): unknown { - const server = this.client.servers.cache.get(data.id) - const oldMember = server?.members.cache.get(data.data?._id?.user) - - if (server && oldMember) { - const newMember = oldMember._update(data.data) - - server.members.cache.set(newMember.id, newMember) - - this.client.emit(Events.SERVER_MEMBER_UPDATE, oldMember, newMember) - - return { newMember, oldMember } - } - - return { oldMember } - } -} diff --git a/deno/client/actions/ServerRoleDelete.ts b/deno/client/actions/ServerRoleDelete.ts deleted file mode 100644 index 1a96da1..0000000 --- a/deno/client/actions/ServerRoleDelete.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerRoleDeleteAction extends Action { - handle(data: { id: string; role_id: string }): unknown { - const server = this.client.servers.cache.get(data.id) - - if (server) { - const role = server.roles.cache.get(data.role_id) - - if (role) { - server.roles._remove(role.id) - this.client.emit(Events.ROLE_DELETE, role) - } - - return { role } - } - - return {} - } -} diff --git a/deno/client/actions/ServerUpdate.ts b/deno/client/actions/ServerUpdate.ts deleted file mode 100644 index 914984b..0000000 --- a/deno/client/actions/ServerUpdate.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { Events } from '../../util/Constants.ts' - -export class ServerUpdateAction extends Action { - handle(data: { id: string; data: APIServer }): unknown { - const oldServer = this.client.servers.cache.get(data.id) - - if (oldServer) { - const newServer = oldServer._update(data.data) - - this.client.servers.cache.set(newServer.id, newServer) - - this.client.emit(Events.SERVER_UPDATE, oldServer, newServer) - - return { newServer, oldServer } - } - - return { oldServer } - } -} diff --git a/deno/client/actions/UserUpdate.ts b/deno/client/actions/UserUpdate.ts deleted file mode 100644 index 32c8483..0000000 --- a/deno/client/actions/UserUpdate.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { User as APIUser } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Action } from './Action.ts' -import { ClientUser } from '../../structures/ClientUser.ts' -import { Events } from '../../util/Constants.ts' - -export class UserUpdateAction extends Action { - handle(data: { id: string; data: APIUser }): unknown { - const oldUser = this.client.users.cache.get(data.id) - - if (oldUser) { - const newUser = oldUser._update(data.data) - - this.client.users.cache.set(newUser.id, newUser) - - if (data.id === this.client.user?.id) { - this.client.user = new ClientUser(this.client, data.data) - } - - this.client.emit(Events.USER_UPDATE, oldUser, newUser) - - return { newUser, oldUser } - } - - return { oldUser } - } -} diff --git a/deno/client/actions/index.ts b/deno/client/actions/index.ts deleted file mode 100644 index 7b4945a..0000000 --- a/deno/client/actions/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './ChannelCreate.ts' -export * from './ChannelDelete.ts' -export * from './ChannelGroupJoin.ts' -export * from './ChannelGroupLeave.ts' -export * from './ChannelStartTyping.ts' -export * from './ChannelStopTyping.ts' -export * from './Message.ts' -export * from './MessageDelete.ts' -export * from './MessageUpdate.ts' -export * from './ServerDelete.ts' -export * from './ServerMemberJoin.ts' -export * from './ServerMemberLeave.ts' -export * from './ServerMemberUpdate.ts' -export * from './ServerRoleDelete.ts' -export * from './ServerUpdate.ts' -export * from './UserUpdate.ts' diff --git a/deno/client/index.ts b/deno/client/index.ts deleted file mode 100644 index 10afd66..0000000 --- a/deno/client/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './BaseClient.ts' -export * from './WebSocket.ts' -export * from './Client.ts' diff --git a/deno/errors/Messages.ts b/deno/errors/Messages.ts deleted file mode 100644 index ab07878..0000000 --- a/deno/errors/Messages.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const Messages = { - INVALID_TYPE: (name: string, expected: string, an = false): string => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, - BITFIELD_INVALID: (bit: unknown): string => `Invalid bitfield flag or number: ${bit}.`, - INVALID_TOKEN: () => 'Invalid token received' -} diff --git a/deno/errors/index.ts b/deno/errors/index.ts deleted file mode 100644 index 89366af..0000000 --- a/deno/errors/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Messages } from './Messages.ts' - -const createCustomError = (Base: ErrorConstructor) => { - return class RevoltError extends Base { - constructor(key: K, ...args: Parameters) { - const msg = Messages[key] as (...args: unknown[]) => string - super(msg(...args)) - Base.captureStackTrace(this, RevoltError) - } - } -} - -export const Error = createCustomError(globalThis.Error) -export const TypeError = createCustomError(globalThis.TypeError) -export const RangeError = createCustomError(globalThis.RangeError) diff --git a/deno/index.ts b/deno/index.ts deleted file mode 100644 index c5689e7..0000000 --- a/deno/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { Client } from './client/Client.ts' -export * from './managers/index.ts' -export * from './structures/index.ts' -export * from './util/index.ts' diff --git a/deno/managers/BaseManager.ts b/deno/managers/BaseManager.ts deleted file mode 100644 index b48e969..0000000 --- a/deno/managers/BaseManager.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { Client } from '../client/Client.ts' -import { Collection } from '../util/index.ts' - -export abstract class BaseManager { - readonly cache = new Collection() - - constructor(protected readonly client: Client) {} - - _add(raw: R): Holds { - if (!this.holds) throw new Error('No "holds" exists.') - const obj = new this.holds(this.client, raw) - this.cache.set(obj.id, obj) - return obj - } - - _remove(id: string): void { - this.cache.delete(id) - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - abstract readonly holds: (new (...args: any[]) => Holds) | null - - resolve(resolvable: Holds): Holds | null - resolve(resolvable: string | R): Holds | null - resolve(resolvable: string | R | Holds): Holds | null - resolve(resolvable: string | R | Holds): Holds | null { - if (resolvable == null) return null - if (typeof resolvable === 'string') return this.cache.get(resolvable) ?? null - if (this.holds && resolvable instanceof this.holds) return resolvable - const raw = resolvable as unknown as { _id: string } - if ('_id' in raw) return this.cache.get(raw._id) ?? null - return null - } - - resolveId(resolvable: string | Holds | R): string | null { - if (resolvable == null) return null - if (typeof resolvable === 'string') return resolvable - if (this.holds && resolvable instanceof this.holds) return resolvable.id - const raw = resolvable as unknown as { _id: string } - if ('_id' in raw) raw._id ?? null - return null - } - - valueOf(): this['cache'] { - return this.cache - } -} diff --git a/deno/managers/ChannelManager.ts b/deno/managers/ChannelManager.ts deleted file mode 100644 index 78a7b19..0000000 --- a/deno/managers/ChannelManager.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Channel, NotesChannel } from '../structures/index.ts' -import { ChannelTypes } from '../util/index.ts' - -export type ChannelResolvable = Channel | APIChannel | string - -export class ChannelManager extends BaseManager { - holds = null - - _add(raw: APIChannel): Channel { - const channel = Channel.create(this.client, raw) - - if (channel.type === ChannelTypes.NOTES && this.client.user) { - this.client.user.notes = channel as NotesChannel - } - - this.cache.set(channel.id, channel) - - return channel - } - - _remove(id: string): void { - const channel = this.cache.get(id) - - if (channel?.inServer()) { - channel.server?.channels.cache.delete(id) - } - - super._remove(id) - } - - async delete(channel: ChannelResolvable): Promise { - const id = this.resolveId(channel) - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable') - await this.client.api.delete(`/channels/${id}`) - } - - async fetch(channel: ChannelResolvable, { force = true } = {}): Promise { - const id = this.resolveId(channel) - - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable') - - if (!force) { - const channel = this.cache.get(id) - if (channel) return channel - } - - const data = (await this.client.api.get(`/channels/${id}`)) as APIChannel - - return this._add(data) - } - - resolve(channel: ChannelResolvable): Channel | null { - if (channel instanceof Channel) return channel - return super.resolve(channel) - } - - resolveId(channel: ChannelResolvable): string | null { - if (channel instanceof Channel) return channel.id - return super.resolveId(channel) - } -} diff --git a/deno/managers/MessageManager.ts b/deno/managers/MessageManager.ts deleted file mode 100644 index b4ffda7..0000000 --- a/deno/managers/MessageManager.ts +++ /dev/null @@ -1,154 +0,0 @@ -import type { User as APIUser, Message as APIMessage, Member as APIMember } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Channel, Message, ServerMember, User } from '../structures/index.ts' -import { Collection, UUID } from '../util/index.ts' - -export type MessageResolvable = Message | APIMessage | string - -export interface EditMessageOptions { - content?: string -} - -export interface MessageOptions { - content: string - replies?: unknown[] - attachments?: string[] -} - -export interface SearchMessageQuery { - query: string - limit?: number - before?: string - after?: string - sort?: 'Relevance' | 'Latest' | 'Oldest' - include_users?: boolean -} - -type SearchResultWithUsers = { - users: Collection - messages: Collection - members: Collection -} - -export class MessageManager extends BaseManager { - holds = Message - constructor(protected readonly channel: Channel) { - super(channel.client) - } - - private async _fetchId(messageId: string) { - const data = await this.client.api.get(`/channels/${this.channel.id}/messages/${messageId}`) - return this._add(data) - } - - private async _fetchMany(withUsers = true) { - const { messages } = await this.client.api.get(`/channels/${this.channel.id}/messages?include_users=${withUsers}`) - return (messages as APIMessage[]).reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) - } - - async send(_options: MessageOptions | string): Promise { - const { content, replies, attachments }: MessageOptions = - typeof _options === 'object' - ? { ..._options } - : { - content: _options - } - - const data = await this.client.api.post(`/channels/${this.channel.id}/messages`, { - body: { - content, - nonce: UUID.generate(), - replies, - attachments - } - }) - - return this._add(data) - } - - async ack(message: MessageResolvable): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.put(`/channels/${this.channel.id}/ack/${id}`) - } - - async delete(message: MessageResolvable): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.delete(`/channels/${this.channel.id}/messages/${id}`) - } - - async edit(message: MessageResolvable, options: EditMessageOptions): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.patch(`/channels/${this.channel.id}/messages/${id}`, { body: options }) - } - - async search(query: SearchMessageQuery & { include_users: true }): Promise - async search(query: SearchMessageQuery): Promise> - async search(query: SearchMessageQuery): Promise | SearchResultWithUsers> { - if (query.include_users) { - const response = (await this.client.api.post(`/channels/${this.channel.id}/search`, { body: query })) as { - users: APIUser[] - messages: APIMessage[] - members: APIMember[] - } - - const users = response.users.reduce((coll, cur) => { - const user = this.client.users._add(cur) - coll.set(user.id, user) - return coll - }, new Collection()) - - const messages = response.messages.reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) - - const server = this.client.servers.cache.get(response.members[0]?._id.server) - - if (server) { - const members = response.members.reduce((coll, cur) => { - const member = server!.members._add(cur) - coll.set(cur._id.user, member) - return coll - }, new Collection()) - - return { messages, users, members } - } - - return { messages, users, members: new Collection() } - } - - const response = (await this.client.api.post(`/channels/${this.channel.id}/search`, { body: query })) as APIMessage[] - - return response.reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) - } - - fetch(messageId: string): Promise - fetch(options: { includeUsers: true }): Promise<{ - users: Collection - messages: Collection - }> - fetch(options?: { includeUsers?: false }): Promise> - fetch(options?: string | { includeUsers?: boolean }): Promise< - | Collection - | { - users: Collection - messages: Collection - } - | Message - > { - return typeof options === 'string' ? this._fetchId(options) : this._fetchMany(options?.['includeUsers']) - } -} diff --git a/deno/managers/RoleManager.ts b/deno/managers/RoleManager.ts deleted file mode 100644 index 02c10d1..0000000 --- a/deno/managers/RoleManager.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Role as APIRole } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Role, Server } from '../structures/index.ts' - -export type RoleResolvable = Role | string - -export class RoleManager extends BaseManager { - holds = Role - constructor(protected readonly server: Server) { - super(server.client) - } - - _add(data: APIRole & { id: string }): Role { - const role = new Role(this.server, data) - this.cache.set(role.id, role) - return role - } - - async create(name: string): Promise { - const { id, role } = await this.client.api.post(`/servers/${this.server.id}/roles`, { body: { name } }) - return this._add(Object.assign(role, { id })) - } - - async delete(role: RoleResolvable): Promise { - const id = this.resolveId(role) - if (!id) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable') - await this.client.api.delete(`/servers/${this.server.id}/roles/${id}`) - } -} diff --git a/deno/managers/ServerChannelManager.ts b/deno/managers/ServerChannelManager.ts deleted file mode 100644 index de7bacc..0000000 --- a/deno/managers/ServerChannelManager.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Server, ServerChannel, TextChannel, VoiceChannel } from '../structures/index.ts' -import { UUID } from '../util/index.ts' - -type APIServerChannel = Extract - -export type ServerChannelResolvable = ServerChannel | APIServerChannel | string - -export interface CreateChannelOptions { - name: string - type?: 'Text' | 'Voice' - description?: string -} - -export class ServerChannelManager extends BaseManager { - holds = ServerChannel - constructor(protected readonly server: Server) { - super(server.client) - } - - _add(data: APIChannel): ServerChannel { - let channel: ServerChannel - - switch (data.channel_type) { - case 'TextChannel': - channel = new TextChannel(this.client, data) - break - case 'VoiceChannel': - channel = new VoiceChannel(this.client, data) - break - default: - throw new Error(`Unknown channel type: ${data.channel_type}`) - } - - this.cache.set(channel.id, channel) - - return channel - } - - async create({ name, type = 'Text', description }: CreateChannelOptions): Promise { - const data = await this.client.api.post(`/servers/${this.server.id}/channels`, { - body: { - name, - type, - description, - nonce: UUID.generate() - } - }) - return this._add(data) - } - - async fetch(channel: ServerChannelResolvable, { force = true } = {}): Promise { - const id = this.resolveId(channel) - - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ServerChannelResolvable') - - if (!force) { - const channel = this.cache.get(id) - if (channel) return channel - } - - const data = await this.client.api.get(`/servers/${this.server.id}/channels/${id}`) - - return this._add(data) - } -} diff --git a/deno/managers/ServerManager.ts b/deno/managers/ServerManager.ts deleted file mode 100644 index 941bab7..0000000 --- a/deno/managers/ServerManager.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Server } from '../structures/index.ts' -import { UUID } from '../util/index.ts' - -export type ServerResolvable = Server | APIServer | string - -export interface EditServerOptions { - name?: string - description?: string -} - -export class ServerManager extends BaseManager { - readonly holds = Server - - _remove(id: string): void { - const server = this.cache.get(id) - - for (const id of server?.channels.cache.keys() ?? []) { - this.client.channels._remove(id) - } - - return super._remove(id) - } - - async create(name: string): Promise { - const { server } = await this.client.api.post('/servers/create', { - body: { - name, - nonce: UUID.generate() - } - }) - return this._add(server) - } - - async edit(server: ServerResolvable, options: EditServerOptions): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.patch(`/servers/${id}`, { body: options }) - } - - async ack(server: ServerResolvable): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.put(`/servers/${id}/ack`) - } - - async delete(server: ServerResolvable): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.delete(`/servers/${id}`) - } - - async fetch(server: ServerResolvable, { force = true } = {}): Promise { - const id = this.resolveId(server) - - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - - if (!force) { - const server = this.cache.get(id) - if (server) return server - } - - const data = (await this.client.api.get(`/servers/${id}`)) as APIServer - - return this._add(data) - } -} diff --git a/deno/managers/ServerMemberManager.ts b/deno/managers/ServerMemberManager.ts deleted file mode 100644 index 104ba86..0000000 --- a/deno/managers/ServerMemberManager.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { Member as APIMember } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Server, ServerMember, User } from '../structures/index.ts' -import { Collection } from '../util/index.ts' - -export type ServerMemberResolvable = ServerMember | User | APIMember | string - -export interface EditServerMemberOptions { - nickname?: string - avatar?: string - roles?: string[] -} - -export class ServerMemberManager extends BaseManager { - holds = ServerMember - constructor(protected readonly server: Server) { - super(server.client) - } - - async edit(member: ServerMemberResolvable, options: EditServerMemberOptions): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.patch(`/servers/${this.server.id}/members/${id}`, { body: { ...options } }) - } - - async ban(member: ServerMemberResolvable, reason?: string): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.put(`/servers/${this.server.id}/bans/${id}`, { body: { reason } }) - } - - async kick(member: ServerMemberResolvable): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.delete(`/servers/${this.server.id}/members/${id}`) - } - - async unban(member: ServerMemberResolvable): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.delete(`/servers/${this.server.id}/bans/${id}`) - } - - async fetch(member: ServerMemberResolvable): Promise - async fetch(): Promise> - async fetch(member?: ServerMemberResolvable): Promise> { - if (typeof member !== 'undefined') { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - const data = await this.client.api.get(`/servers/${this.server.id}/members/${id}`) - return this._add(data) - } - - const { members } = (await this.client.api.get(`/servers/${this.server.id}/members`)) as { members: APIMember[] } - - return members.reduce((coll, cur) => { - const member = this._add(cur) - coll.set(member.id, member) - return coll - }, new Collection()) - } - - resolveId(member: ServerMemberResolvable): string | null { - if (member == null) return null - if (member instanceof ServerMember || member instanceof User) return member.id - if (typeof member === 'string') return member - if ('_id' in member) return member._id.user - return null - } -} diff --git a/deno/managers/UserManager.ts b/deno/managers/UserManager.ts deleted file mode 100644 index fa9aff3..0000000 --- a/deno/managers/UserManager.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { User as APIUser } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { BaseManager } from './BaseManager.ts' -import { TypeError } from '../errors/index.ts' -import { Message, User } from '../structures/index.ts' - -export type UserResolvable = User | APIUser | Message | string - -export class UserManager extends BaseManager { - holds = User - - async fetch(user: UserResolvable, { force = true } = {}): Promise { - const userId = this.resolveId(user) - - if (!userId) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - - if (!force) { - const user = this.cache.get(userId) - if (user) return user - } - - const data = (await this.client.api.get(`/users/${userId}`)) as APIUser - - return this._add(data) - } - - resolve(resolvable: Message | User): User - resolve(resolvable: string | APIUser): User | null - resolve(resolvable: User | APIUser | string | Message): User | null { - if (resolvable instanceof Message) return resolvable.author - return super.resolve(resolvable) - } - - resolveId(resolvable: UserResolvable): string | null { - if (resolvable instanceof Message) return resolvable.authorId - return super.resolveId(resolvable) - } -} diff --git a/deno/managers/index.ts b/deno/managers/index.ts deleted file mode 100644 index 6d7d6d2..0000000 --- a/deno/managers/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './BaseManager.ts' -export * from './ChannelManager.ts' -export * from './MessageManager.ts' -export * from './RoleManager.ts' -export * from './ServerChannelManager.ts' -export * from './ServerMemberManager.ts' -export * from './ServerManager.ts' -export * from './UserManager.ts' diff --git a/deno/rest/APIRequest.ts b/deno/rest/APIRequest.ts deleted file mode 100644 index 8904812..0000000 --- a/deno/rest/APIRequest.ts +++ /dev/null @@ -1,41 +0,0 @@ - - -export interface APIRequestOptions { - method?: RequestMethod - body?: unknown - headers?: HeadersInit - timeout?: number -} - -export enum RequestMethod { - Delete = 'DELETE', - Get = 'GET', - Patch = 'PATCH', - Post = 'POST', - Put = 'PUT' -} - -export class APIRequest { - body?: unknown - headers?: HeadersInit - method = RequestMethod.Get - retries = 0 - timeout: number - constructor(public path: string, { method, headers, body, timeout }: APIRequestOptions = {}) { - this.method = method ?? this.method - this.body = body - this.headers = headers - this.timeout = timeout ?? 0 - } - - execute(): Promise { - const controller = new AbortController() - const timeout = setTimeout(() => controller.abort(), this.timeout) - return fetch(this.path, { - method: this.method, - body: this.body ? JSON.stringify(this.body) : null, - headers: this.headers, - signal: controller.signal - }).finally(() => clearTimeout(timeout)) - } -} diff --git a/deno/rest/Endpoints.ts b/deno/rest/Endpoints.ts deleted file mode 100644 index 4d02e32..0000000 --- a/deno/rest/Endpoints.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { BaseClientOptions } from '../client/index.ts' - -export type EndpointsOptions = BaseClientOptions['endpoints'] - -export class Endpoints { - constructor(private readonly options: EndpointsOptions) {} - - get CDN(): string { - return this.options.cdn - } - - get INVITE(): string { - return this.options.invite - } - - get API(): string { - return this.options.api - } - - defaultAvatar(id: string): string { - return `${this.API}/users/${id}/default_avatar` - } - - avatar(hash: string, filename: string, size = 1024): string { - return `${this.CDN}/avatars/${hash}/${filename}?max_side=${size}` - } - - icon(hash: string, size = 1024): string { - return `${this.CDN}/icons/${hash}?max_side=${size}` - } - - invite(code: string): string { - return `${this.INVITE}/${code}` - } - - banner(hash: string, size = 1024): string { - return `${this.CDN}/banners/${hash}?max_side=${size}` - } -} diff --git a/deno/rest/HTTPError.ts b/deno/rest/HTTPError.ts deleted file mode 100644 index 1ec1589..0000000 --- a/deno/rest/HTTPError.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { APIRequest, RequestMethod } from './APIRequest.ts' - -export class HTTPError extends Error { - code: number - method: RequestMethod - path: string - constructor(message: string, name: string, code: number, request: APIRequest) { - super(message) - this.name = name - this.code = code ?? 500 - this.method = request.method - this.path = request.path - } -} diff --git a/deno/rest/REST.ts b/deno/rest/REST.ts deleted file mode 100644 index 3cf163b..0000000 --- a/deno/rest/REST.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -/* eslint-disable @typescript-eslint/no-empty-function */ - -import type { APIRoutes } from 'https://deno.land/x/revolt_api@0.4.0/routes.ts' -import { APIRequest, APIRequestOptions, RequestMethod } from './APIRequest.ts' -import { HTTPError } from './HTTPError.ts' -import { BaseClientOptions } from '../client/BaseClient.ts' - -type GetRoutes = Extract -type PostRoutes = Extract -type DeleteRoutes = Extract -type PatchRoutes = Extract -type PutRoutes = Extract - -export const parseResponse = (res: Response): Promise => { - if (res.headers.get('Content-Type')?.startsWith('application/json')) { - return res.json() - } - return res.arrayBuffer() -} - -export type RESTOptions = BaseClientOptions['rest'] - -export class REST { - #token: string | null = null - #bot = true - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - debug(_message: string) {} - constructor(private readonly options: RESTOptions) {} - - setToken(token: string | null, bot = true): this { - this.#token = token - this.#bot = bot - return this - } - - private get headers() { - if (!this.#token) return {} - return { - [`x-${this.#bot ? 'bot' : 'session'}-token`]: this.#token - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async request(request: APIRequest): Promise { - let res: Response - - try { - res = await request.execute() - } catch (error) { - if (request.retries === this.options.retries) { - if (error instanceof Response) { - throw new HTTPError(error.statusText, error.constructor.name, error.status, request) - } - } - - request.retries++ - return this.request(request) - } - - if (res.ok) { - return parseResponse(res) - } - - // TODO: Handle ratelimit - if (res.status === 429) { - this.debug(`Hit a 429 while executing a request. - Method: ${request.method} - Path: ${request.path} - Limit: ${this.options.retries} - Timeout: ${this.options.timeout}ms`) - } - - if (res.status >= 500 && res.status < 600) { - if (request.retries === this.options.retries) { - throw new HTTPError(res.statusText, res.constructor.name, res.status, request) - } - - request.retries++ - - return this.request(request) - } - - throw new HTTPError(res.statusText, res.constructor.name, res.status, request) - } - - private getOptions(options: APIRequestOptions, method: RequestMethod) { - return { - ...options, - headers: this.headers, - timeout: this.options.timeout, - method - } - } - - get(path: Path, options: APIRequestOptions = {}): Promise { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Get))) - } - - delete( - path: Path, - options: APIRequestOptions = {} - ): Promise { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Delete))) - } - - post(path: Path, options: APIRequestOptions = {}): Promise { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Post))) - } - - put(path: Path, options: APIRequestOptions = {}): Promise { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Put))) - } - - patch(path: Path, options: APIRequestOptions = {}): Promise { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Patch))) - } -} diff --git a/deno/rest/index.ts b/deno/rest/index.ts deleted file mode 100644 index ab50b5d..0000000 --- a/deno/rest/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './REST.ts' -export * from './Endpoints.ts' diff --git a/deno/structures/Base.ts b/deno/structures/Base.ts deleted file mode 100644 index ce993a6..0000000 --- a/deno/structures/Base.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Client } from '../client/Client.ts' - -type ID = { _id: string } | { id: string } | { _id: { user: string } } - -export abstract class Base = Partial> { - id!: string - constructor(public readonly client: Client) {} - - _update(data: APIBase): this { - const clone = this._clone() - clone._patch(data) - return clone - } - - protected _patch(data: APIBase): this { - if ('id' in data) this.id = data.id! - if ('_id' in data) { - if (typeof data._id === 'string') this.id = data._id - if (typeof data._id === 'object') this.id = data._id.user - } - return this - } - - protected _clone(): this { - return Object.assign(Object.create(this), this) - } -} diff --git a/deno/structures/Category.ts b/deno/structures/Category.ts deleted file mode 100644 index 1f29ba1..0000000 --- a/deno/structures/Category.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { Category as APICategory } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, Server, ServerChannel } from './index.ts' -import { Collection } from '../util/index.ts' - -export class Category extends Base { - name!: string - protected _children: string[] = [] - constructor(public server: Server, data: APICategory) { - super(server.client) - this._patch(data) - } - - protected _patch(data: APICategory): this { - super._patch(data) - - if (data.title) { - this.name = data.title - } - - if (Array.isArray(data.channels)) { - this._children = data.channels - } - - return this - } - - get children(): Collection { - const coll = new Collection() - - for (const childId of this._children) { - const child = this.server.channels.cache.get(childId) - if (child) coll.set(child.id, child) - } - - return coll - } - - toString(): string { - return this.name - } -} diff --git a/deno/structures/Channel.ts b/deno/structures/Channel.ts deleted file mode 100644 index aa31643..0000000 --- a/deno/structures/Channel.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, DMChannel, GroupChannel, NotesChannel, ServerChannel, TextChannel, VoiceChannel } from './index.ts' -import type { Client } from '../client/Client.ts' -import { ChannelTypes, UUID } from '../util/index.ts' - -export abstract class Channel extends Base { - type: ChannelTypes | 'UNKNOWN' = 'UNKNOWN' - - constructor(client: Client, data: T) { - super(client) - this._patch(data) - } - - static create(client: Client, data: APIChannel): Channel { - let channel: Channel - - switch (data.channel_type) { - case 'TextChannel': - channel = new TextChannel(client, data) - break - case 'VoiceChannel': - channel = new VoiceChannel(client, data) - break - case 'DirectMessage': - channel = new DMChannel(client, data) - break - case 'Group': - channel = new GroupChannel(client, data) - break - case 'SavedMessages': - channel = new NotesChannel(client, data) - break - } - - return channel - } - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - async delete(): Promise { - await this.client.channels.delete(this) - } - - isText(): this is TextChannel | GroupChannel | DMChannel { - return 'messages' in this - } - - isVoice(): this is VoiceChannel { - return this.type === ChannelTypes.VOICE - } - - isGroup(): this is GroupChannel { - return this.type === ChannelTypes.GROUP - } - - inServer(): this is ServerChannel { - return 'serverId' in this - } - - toString(): string { - return `<#${this.id}>` - } - - fetch(force = true): Promise { - return this.client.channels.fetch(this, { force }) - } -} diff --git a/deno/structures/ClientUser.ts b/deno/structures/ClientUser.ts deleted file mode 100644 index 5893829..0000000 --- a/deno/structures/ClientUser.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { NotesChannel } from './index.ts' -import { User } from './User.ts' - -export class ClientUser extends User { - notes: NotesChannel | null = null - - async setUsername(username: string, password?: string): Promise { - await this.client.api.patch('/users/@me/username', { - body: { username, password } - }) - } - - async setStatus(status: { text?: string; presence?: 'Online' | 'Idle' | 'Busy' | 'Invisible' }): Promise { - await this.client.api.patch('/users/@me', { body: { status } }) - } -} diff --git a/deno/structures/DMChannel.ts b/deno/structures/DMChannel.ts deleted file mode 100644 index 781365e..0000000 --- a/deno/structures/DMChannel.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Channel, Message } from './index.ts' -import { TextBasedChannel } from './interfaces/index.ts' -import { Client, MessageManager, MessageOptions } from '../index.ts' -import { ChannelTypes, DEFAULT_PERMISSION_DM } from '../util/index.ts' - -type APIDirectChannel = Extract - -export class DMChannel extends Channel implements TextBasedChannel { - readonly type = ChannelTypes.DM - active!: boolean - permissions = DEFAULT_PERMISSION_DM - messages = new MessageManager(this) - lastMessageId: string | null = null - - constructor(client: Client, data: APIDirectChannel) { - super(client, data) - this._patch(data) - } - - protected _patch(data: APIDirectChannel): this { - super._patch(data) - - if (typeof data.active === 'boolean') this.active = data.active - if (data.last_message_id) this.lastMessageId = data.last_message_id - - return this - } - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } - - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } -} diff --git a/deno/structures/GroupChannel.ts b/deno/structures/GroupChannel.ts deleted file mode 100644 index 09f45eb..0000000 --- a/deno/structures/GroupChannel.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { User, Channel, Message } from './index.ts' -import { TextBasedChannel } from './interfaces/index.ts' -import type { Client } from '../client/Client.ts' -import { TypeError } from '../errors/index.ts' -import { MessageManager, MessageOptions, UserResolvable } from '../managers/index.ts' -import { ChannelPermissions, ChannelTypes, Collection } from '../util/index.ts' - -type APIGroupChannel = Extract - -export class GroupChannel extends Channel implements TextBasedChannel { - name!: string - description: string | null = null - ownerId!: string - readonly type = ChannelTypes.GROUP - permissions!: Readonly - icon: string | null = null - messages = new MessageManager(this) - lastMessageId: string | null = null - users = new Collection() - nsfw = false - - constructor(client: Client, data: APIGroupChannel) { - super(client, data) - this._patch(data) - } - - protected _patch(data: APIGroupChannel): this { - super._patch(data) - - if ('description' in data) { - this.description = data.description ?? null - } - - if (Array.isArray(data.recipients)) { - this.users.clear() - for (const userId of data.recipients) { - const user = this.client.users.cache.get(userId) - if (user) this.users.set(user.id, user) - } - } - - if (typeof data.permissions === 'number') { - this.permissions = new ChannelPermissions(data.permissions).freeze() - } - - if (data.owner) { - this.ownerId = data.owner - } - - if ('icon' in data) { - this.icon = data.icon?._id ?? null - } - - if (data.name) { - this.name = data.name - } - - if (data.last_message_id) this.lastMessageId = data.last_message_id - - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - - return this - } - - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } - - async add(user: UserResolvable): Promise { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - await this.client.api.put(`/channels/${this.id}/recipients/${id}`) - } - async remove(user: UserResolvable): Promise { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - await this.client.api.delete(`/channels/${this.id}/recipients/${id}`) - } - async leave(): Promise { - await super.delete() - } - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } - - iconURL(options?: { size: number }): string | null { - if (!this.icon) return null - return this.client.endpoints.icon(this.icon, options?.size) - } - - get owner(): User | null { - return this.client.users.cache.get(this.ownerId) ?? null - } -} diff --git a/deno/structures/Mentions.ts b/deno/structures/Mentions.ts deleted file mode 100644 index a34d88e..0000000 --- a/deno/structures/Mentions.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Message, ServerMember, User } from './index.ts' -import { Client } from '../client/Client.ts' -import { TypeError } from '../errors/index.ts' -import { UserResolvable } from '../managers/index.ts' -import { Collection } from '../util/index.ts' - -export class Mentions { - public readonly client: Client - - constructor(public message: Message, protected _users: string[]) { - this.client = message.client - } - - has(user: UserResolvable): boolean { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - return this._users.includes(id) - } - - get members(): Collection | null { - const server = this.message.server - - if (!server) return null - - const members = new Collection() - - for (const userId of this._users) { - const member = server.members.cache.get(userId) - if (member) members.set(member.id, member) - } - - return members - } - - get users(): Collection { - const users = new Collection() - - for (const userId of this._users) { - const user = this.client.users.cache.get(userId) - if (user) users.set(user.id, user) - } - - return users - } -} diff --git a/deno/structures/Message.ts b/deno/structures/Message.ts deleted file mode 100644 index 8b29b96..0000000 --- a/deno/structures/Message.ts +++ /dev/null @@ -1,125 +0,0 @@ -import type { Message as APIMessage, SystemMessage, Embed, File } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, DMChannel, GroupChannel, Mentions, Server, ServerMember, TextChannel, User } from './index.ts' -import { Client } from '../client/Client.ts' -import { UUID } from '../util/index.ts' - -export class Message extends Base { - content = '' - channelId!: string - authorId!: string - embeds: Embed[] = [] - attachments: File[] = [] - mentions = new Mentions(this, []) - type: Uppercase = 'TEXT' - editedAt: Date | null = null - constructor(client: Client, data: APIMessage) { - super(client) - this._patch(data) - } - - protected _patch(data: APIMessage): this { - super._patch(data) - - if (Array.isArray(data.embeds)) { - this.embeds = data.embeds - } - - if (Array.isArray(data.attachments)) { - this.attachments = data.attachments - } - - if (Array.isArray(data.mentions)) { - this.mentions = new Mentions(this, data.mentions) - } - - if (data.author) { - this.authorId = data.author - } - - if (data.channel) { - this.channelId = data.channel - } - - if (typeof data.content === 'string') { - this.content = data.content - } - - if (data.system) { - this.type = data.system.type.toUpperCase() as Uppercase - } - - if (data.edited) { - this.editedAt = new Date(data.edited) - } - - return this - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - get editedTimestamp(): number | null { - return this.editedAt?.getTime() ?? null - } - - async ack(): Promise { - await this.channel.messages.ack(this) - } - - async delete(): Promise { - await this.channel.messages.delete(this) - } - - async reply(content: string, mention = true): Promise { - return this.channel.messages.send({ - content, - replies: [{ id: this.id, mention }] - }) - } - - async edit(content: string): Promise { - await this.channel.messages.edit(this, { content }) - } - - fetch(): Promise { - return this.channel.messages.fetch(this.id) - } - - get system(): boolean { - return this.type !== 'TEXT' - } - - inServer(): this is this & { serverId: string; server: Server; channel: TextChannel } { - return this.channel.inServer() - } - - get author(): User | null { - return this.client.users.cache.get(this.authorId) ?? null - } - - get channel(): TextChannel | DMChannel | GroupChannel { - return this.client.channels.cache.get(this.channelId) as TextChannel - } - - get serverId(): string | null { - const channel = this.channel - return channel.inServer() ? channel.serverId : null - } - - get server(): Server | null { - return this.client.servers.cache.get(this.serverId as string) ?? null - } - - get member(): ServerMember | null { - return this.server?.members.cache.get(this.authorId) ?? null - } - - get url(): string { - return `https://app.revolt.chat/${this.serverId ? `server/${this.serverId}` : ''}/channel/${this.channelId}/${this.id}` - } -} diff --git a/deno/structures/MessageEmbed.ts b/deno/structures/MessageEmbed.ts deleted file mode 100644 index 7e5c5e4..0000000 --- a/deno/structures/MessageEmbed.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { Embed, Special } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' - -export type EmbedImage = Extract -export type EmbedVideo = Extract -export type EmbedSpecial = Special - -export class MessageEmbed { - type: Embed['type'] = 'Website' - url?: string - special?: EmbedSpecial - title?: string - description?: string - image?: EmbedImage - video?: EmbedVideo - site_name?: string - icon_url?: string - color?: string - - constructor(data: Partial = {}) { - Object.assign(this, data) - } - - setTitle(title: string): this { - this.title = title - return this - } - - setIcon(iconURL: string): this { - this.icon_url = iconURL - return this - } - - setColor(color: string): this { - this.color = color - return this - } - - setDescription(description: string): this { - this.description = description - return this - } - - setURL(url: string): this { - this.url = url - return this - } - - toJSON(): unknown { - return { - title: this.title, - type: this.type, - description: this.description, - url: this.url - } - } -} diff --git a/deno/structures/NotesChannel.ts b/deno/structures/NotesChannel.ts deleted file mode 100644 index d5fefcf..0000000 --- a/deno/structures/NotesChannel.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { User, Channel, Message } from './index.ts' -import { TextBasedChannel } from './interfaces/index.ts' -import { Client } from '../client/Client.ts' -import { MessageManager, MessageOptions } from '../managers/index.ts' -import { ChannelTypes } from '../util/index.ts' - -type APINotesChannel = Extract - -export class NotesChannel extends Channel implements TextBasedChannel { - readonly type = ChannelTypes.NOTES - userId!: string - lastMessageId: string | null = null - messages = new MessageManager(this) - constructor(client: Client, data: APINotesChannel) { - super(client, data) - this._patch(data) - } - - protected _patch(data: APINotesChannel): this { - super._patch(data) - - if (data.user) { - this.userId = data.user - } - - return this - } - - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } - - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } - - get user(): User { - return this.client.user! - } -} diff --git a/deno/structures/Role.ts b/deno/structures/Role.ts deleted file mode 100644 index b851df1..0000000 --- a/deno/structures/Role.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { Role as APIRole } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, Server, Overwrite } from './index.ts' -import { UUID, ChannelPermissions } from '../util/index.ts' - -export class Role extends Base { - name!: string - color: string | null = null - hoist = false - rank!: number - overwrite!: Overwrite - constructor(public server: Server, data: APIRole & { id: string }) { - super(server.client) - this._patch(data) - } - - protected _patch(data: APIRole & { _id?: string }): this { - super._patch(data) - - if (data.name) this.name = data.name - if (typeof data.hoist === 'boolean') this.hoist = data.hoist - if (typeof data.rank === 'number') this.rank = data.rank - if ('colour' in data) this.color = data.colour ?? null - if (data.permissions) { - const { a, d } = data.permissions - this.overwrite = { allow: new ChannelPermissions(a), deny: new ChannelPermissions(d) } - } - - return this - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - get permissions(): Overwrite { - return this.overwrite - } - - async delete(): Promise { - await this.server.roles.delete(this) - } - - toString(): string { - return `<@&${this.id}>` - } -} diff --git a/deno/structures/Server.ts b/deno/structures/Server.ts deleted file mode 100644 index e7c3d2d..0000000 --- a/deno/structures/Server.ts +++ /dev/null @@ -1,117 +0,0 @@ -import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, ServerMember, User, Category } from './index.ts' -import { Client } from '../client/Client.ts' -import { RoleManager, ServerChannelManager, ServerMemberManager } from '../managers/index.ts' -import { Collection, ServerPermissions, UUID } from '../util/index.ts' - -export class Server extends Base { - name!: string - description: string | null = null - ownerId!: string - members = new ServerMemberManager(this) - channels = new ServerChannelManager(this) - roles = new RoleManager(this) - icon: string | null = null - banner: string | null = null - analytics = false - discoverable = false - nsfw = false - permissions!: ServerPermissions - categories = new Collection() - - constructor(client: Client, data: APIServer) { - super(client) - this._patch(data) - } - - protected _patch(data: APIServer): this { - super._patch(data) - - if (Array.isArray(data.categories)) { - this.categories.clear() - for (const cat of data.categories) { - const category = new Category(this, cat) - this.categories.set(category.id, category) - } - } - - if ('icon' in data) { - this.icon = data.icon?._id ?? null - } - - if ('banner' in data) { - this.banner = data.banner?._id ?? null - } - - if (data.owner) { - this.ownerId = data.owner - } - - if (data.name) { - this.name = data.name - } - - if ('description' in data) { - this.description = data.description ?? null - } - - if (Array.isArray(data.channels)) { - for (const id of data.channels) { - const channel = this.client.channels.cache.get(id) - if (channel?.inServer()) this.channels.cache.set(channel.id, channel) - } - } - - if (typeof data.roles === 'object') { - for (const [id, raw] of Object.entries(data.roles)) { - this.roles._add(Object.assign(raw, { id })) - } - } - - if (typeof data.default_permissions === 'number') { - this.permissions = new ServerPermissions(data.default_permissions).freeze() - } - - if (typeof data.analytics === 'boolean') this.analytics = data.analytics - if (typeof data.discoverable === 'boolean') this.discoverable = data.discoverable - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - - return this - } - - async ack(): Promise { - await this.client.servers.ack(this) - } - - async delete(): Promise { - await this.client.servers.delete(this) - } - - iconURL(options?: { size: number }): string | null { - return this.icon ? this.client.endpoints.icon(this.icon, options?.size) : null - } - - bannerURL(options?: { size: number }): string | null { - return this.banner ? this.client.endpoints.banner(this.banner, options?.size) : null - } - - get me(): ServerMember | null { - return this.members.cache.get(this.client.user?.id as string) ?? null - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - get owner(): User | null { - return this.client.users.cache.get(this.ownerId) ?? null - } - - toString(): string { - return this.name - } -} diff --git a/deno/structures/ServerChannel.ts b/deno/structures/ServerChannel.ts deleted file mode 100644 index 845b7f4..0000000 --- a/deno/structures/ServerChannel.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Category, Channel, Server } from './index.ts' -import { Client } from '../client/Client.ts' -import { ChannelPermissions, Collection } from '../util/index.ts' - -type APIServerChannel = Extract - -export interface Overwrite { - allow: ChannelPermissions - deny: ChannelPermissions -} - -export class ServerChannel extends Channel { - name!: string - serverId!: string - description: string | null = null - icon: string | null = null - overwrites = new Collection() - nsfw = false - constructor(client: Client, data: T) { - super(client, data) - this._patch(data) - } - - protected _patch(data: T): this { - super._patch(data) - - if (data.name) this.name = data.name - if (data.server) this.serverId = data.server - if ('description' in data) this.description = data.description ?? null - if ('icon' in data) this.icon = data.icon?._id ?? null - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - if (data.role_permissions) { - this.overwrites.clear() - for (const [id, { a, d }] of Object.entries(data.role_permissions)) { - this.overwrites.set(id, { allow: new ChannelPermissions(a), deny: new ChannelPermissions(d) }) - } - } - - return this - } - - async createInvite(): Promise { - const invite = await this.client.api.post(`/channels/${this.id}/invites`) - return this.client.endpoints.invite(invite._id) - } - - iconURL(options?: { size: number }): string | null { - return this.icon ? this.client.endpoints.icon(this.icon, options?.size) : null - } - - get server(): Server { - return this.client.servers.cache.get(this.serverId) as Server - } - - get category(): Category | null { - return this.server.categories.find(cat => cat.children.has(this.id)) ?? null - } -} diff --git a/deno/structures/ServerMember.ts b/deno/structures/ServerMember.ts deleted file mode 100644 index 1efacc2..0000000 --- a/deno/structures/ServerMember.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { Member as APIMember, File } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, Server, User } from './index.ts' -import { Client } from '../client/Client.ts' - -export class ServerMember extends Base { - serverId!: string - nickname: string | null = null - avatar: File | null = null - constructor(client: Client, data: APIMember) { - super(client) - this._patch(data) - } - - protected _patch(data: APIMember): this { - super._patch(data) - - if ('nickname' in data) { - this.nickname = data.nickname ?? null - } - - if ('avatar' in data) { - this.avatar = data.avatar ?? null - } - - if (data._id) { - this.serverId = data._id.server - this.id = data._id.user - } - - return this - } - - async setNickname(nickname?: string): Promise { - await this.server.members.edit(this, { nickname }) - return this - } - - ban(reason?: string): Promise { - return this.server.members.ban(this, reason) - } - - kick(): Promise { - return this.server.members.kick(this) - } - - leave(): Promise { - return this.client.servers.delete(this.serverId) - } - - displayAvatarURL(options?: { size: number }): string { - return this.user.displayAvatarURL(options) - } - - get user(): User { - return this.client.users.cache.get(this.id)! - } - - get server(): Server { - return this.client.servers.cache.get(this.serverId)! - } - - toString(): string { - return `<@${this.id}>` - } -} diff --git a/deno/structures/TextChannel.ts b/deno/structures/TextChannel.ts deleted file mode 100644 index 3395c58..0000000 --- a/deno/structures/TextChannel.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Message, ServerChannel } from './index.ts' -import { TextBasedChannel } from './interfaces/index.ts' -import { Client } from '../client/Client.ts' -import { MessageManager, MessageOptions } from '../managers/index.ts' -import { ChannelTypes } from '../util/index.ts' - -type APITextChannel = Extract - -export class TextChannel extends ServerChannel implements TextBasedChannel { - lastMessageId: string | null = null - messages = new MessageManager(this) - readonly type = ChannelTypes.TEXT - constructor(client: Client, data: APITextChannel) { - super(client, data) - this._patch(data) - } - - protected _patch(data: APITextChannel): this { - super._patch(data) - - if (data.last_message_id) this.lastMessageId = data.last_message_id - - return this - } - - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } - - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } -} diff --git a/deno/structures/User.ts b/deno/structures/User.ts deleted file mode 100644 index 568160a..0000000 --- a/deno/structures/User.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { User as APIUser, Presence as APIPresence, File } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { Base, DMChannel } from './index.ts' -import { Client } from '../client/Client.ts' -import { Badges, Presence, UUID } from '../util/index.ts' - -export class User extends Base { - username!: string - avatar: File | null = null - status = { - text: null, - presence: Presence.INVISIBLE - } as { - text: string | null - presence: Presence - } - badges!: Badges - bot = false - - constructor(client: Client, data: APIUser) { - super(client) - this._patch(data) - } - - protected _patch(data: APIUser): this { - super._patch(data) - - if (data.username) { - this.username = data.username - } - - if (data.bot) { - this.bot = true - } - - if (typeof data.badges === 'number') { - this.badges = new Badges(data.badges).freeze() - } - - if ('avatar' in data) { - this.avatar = data.avatar ?? null - } - - if ('status' in data) { - const presence = data.status?.presence ? Presence[data.status.presence.toUpperCase() as Uppercase] : Presence.INVISIBLE - this.status.presence = presence - this.status.text = data.status?.text ?? null - } - - return this - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - async block(): Promise { - await this.client.api.put(`/users/${this.id}/block`) - } - - async unblock(): Promise { - await this.client.api.delete(`/users/${this.id}/block`) - } - - async createDM(): Promise { - const data = await this.client.api.get(`/users/${this.id}/dm`) - return this.client.channels._add(data) as DMChannel - } - - avatarURL(options?: { size: number }): string | null { - return this.avatar ? this.client.endpoints.avatar(this.avatar._id, this.avatar.filename, options?.size) : null - } - - displayAvatarURL(options?: { size: number }): string { - return this.avatarURL(options) ?? this.client.endpoints.defaultAvatar(this.id) - } - - fetch(force = true): Promise { - return this.client.users.fetch(this, { force }) - } - - toString(): string { - return `<@${this.id}>` - } -} diff --git a/deno/structures/VoiceChannel.ts b/deno/structures/VoiceChannel.ts deleted file mode 100644 index fb8d347..0000000 --- a/deno/structures/VoiceChannel.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts' -import { ServerChannel } from './index.ts' -import { Client } from '../index.ts' -import { ChannelTypes } from '../util/index.ts' - -type APIVoiceChannel = Extract - -export class VoiceChannel extends ServerChannel { - readonly type = ChannelTypes.VOICE - constructor(client: Client, data: APIVoiceChannel) { - super(client, data) - this._patch(data) - } - - protected _patch(data: APIVoiceChannel): this { - super._patch(data) - return this - } - - async ack(): Promise { - throw new TypeError('Cannot ack voice channel') - } -} diff --git a/deno/structures/index.ts b/deno/structures/index.ts deleted file mode 100644 index 120ad0a..0000000 --- a/deno/structures/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './Base.ts' -export * from './Category.ts' -export * from './Channel.ts' -export * from './ClientUser.ts' -export * from './DMChannel.ts' -export * from './GroupChannel.ts' -export * from './Mentions.ts' -export * from './Message.ts' -export * from './NotesChannel.ts' -export * from './Role.ts' -export * from './Server.ts' -export * from './ServerChannel.ts' -export * from './ServerMember.ts' -export * from './TextChannel.ts' -export * from './User.ts' -export * from './VoiceChannel.ts' diff --git a/deno/structures/interfaces/TextBasedChannel.ts b/deno/structures/interfaces/TextBasedChannel.ts deleted file mode 100644 index fa4d7b3..0000000 --- a/deno/structures/interfaces/TextBasedChannel.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { MessageManager, Message, MessageOptions } from '../../index.ts' - -export interface TextBasedChannel { - messages: MessageManager - lastMessageId: string | null - lastMessage: Message | null - send(options: MessageOptions | string): Promise -} diff --git a/deno/structures/interfaces/index.ts b/deno/structures/interfaces/index.ts deleted file mode 100644 index cad0d17..0000000 --- a/deno/structures/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TextBasedChannel.ts' diff --git a/deno/util/Badges.ts b/deno/util/Badges.ts deleted file mode 100644 index be6c83a..0000000 --- a/deno/util/Badges.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BitField } from './BitField.ts' - -export type BadgeString = keyof typeof FLAGS -export type BadgesResolvable = number | BadgeString | BadgesResolvable[] - -export declare interface Badges { - serialize(): Record - any(bit: BadgesResolvable): boolean - add(...bits: BadgesResolvable[]): this - remove(...bits: BadgesResolvable[]): this - has(bit: BadgesResolvable): boolean -} - -const FLAGS = { - DEVELOPER: 1 << 0, - TRANSLATOR: 1 << 1, - SUPPORTER: 1 << 2, - RESPONSIBLE_DISCLOSURE: 1 << 3, - REVOLT_TEAM: 1 << 4, - EARLY_ADOPTER: 1 << 8 -} as const - -export class Badges extends BitField { - static FLAGS: typeof FLAGS - constructor(bits?: BadgesResolvable) { - super(bits) - } - static resolve(bit: BadgesResolvable): number { - return super.resolve(bit) - } -} - -Badges.FLAGS = FLAGS diff --git a/deno/util/BitField.ts b/deno/util/BitField.ts deleted file mode 100644 index 8e416cd..0000000 --- a/deno/util/BitField.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { RangeError } from '../errors/index.ts' - -const DEFAULT_BIT = 0 - -export type BitFieldResolvable = BitField | number | string | BitFieldResolvable[] - -export class BitField { - static FLAGS: Record = {} - bitfield = DEFAULT_BIT - constructor(bits: BitFieldResolvable = DEFAULT_BIT) { - this.bitfield = this.self.resolve(bits) - } - - static resolve(bit: BitFieldResolvable): number { - if (bit instanceof BitField) return bit.bitfield - if (typeof bit === 'number' && bit >= DEFAULT_BIT) return bit - if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, DEFAULT_BIT) - if (typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit] - throw new RangeError('BITFIELD_INVALID', bit) - } - get self(): { - FLAGS: Record - resolve(bit: BitFieldResolvable): number - new (bits?: BitFieldResolvable): BitField - } { - return this.constructor as unknown as { - FLAGS: Record - resolve(bit: BitFieldResolvable): number - new (bits?: BitFieldResolvable): BitField - } - } - - any(bit: BitFieldResolvable): boolean { - bit = this.self.resolve(bit) - return (this.bitfield & bit) !== DEFAULT_BIT - } - - has(bit: BitFieldResolvable): boolean { - bit = this.self.resolve(bit) - return (this.bitfield & bit) === bit - } - - toArray(): string[] { - return Object.keys(this.self.FLAGS).filter(bit => this.has(bit)) - } - - add(...bits: BitFieldResolvable[]): this { - let total = 0 - - for (const bit of bits) { - total |= this.self.resolve(bit) - } - - if (Object.isFrozen(this)) return new this.self(this.bitfield | total) as this - - this.bitfield |= total - - return this - } - - remove(...bits: BitFieldResolvable[]): this { - let total = 0 - - for (const bit of bits) { - total |= this.self.resolve(bit) - } - - if (Object.isFrozen(this)) return new this.self(this.bitfield & ~total) as this - - this.bitfield &= ~total - - return this - } - - freeze(): Readonly { - return Object.freeze(this) - } - - valueOf(): number { - return this.bitfield - } - - serialize(): Record { - const serialized: Record = {} - for (const [flag, bit] of Object.entries(this.self.FLAGS)) serialized[flag] = this.has(bit) - return serialized - } - - *[Symbol.iterator](): Iterable { - yield* this.toArray() - } -} diff --git a/deno/util/Collection.ts b/deno/util/Collection.ts deleted file mode 100644 index 150d85a..0000000 --- a/deno/util/Collection.ts +++ /dev/null @@ -1 +0,0 @@ -export { Collection } from 'https://raw.githubusercontent.com/discordjs/discord.js/main/packages/collection/src/index.ts' diff --git a/deno/util/Constants.ts b/deno/util/Constants.ts deleted file mode 100644 index 8f6e0d3..0000000 --- a/deno/util/Constants.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { UUID } from './UUID.ts' -import { BaseClientOptions } from '../client/BaseClient.ts' - -export enum Events { - DEBUG = 'debug', - ERROR = 'error', - RAW = 'raw', - MESSAGE = 'message', - READY = 'ready', - CHANNEL_CREATE = 'channelCreate', - CHANNEL_DELETE = 'channelDelete', - SERVER_DELETE = 'serverDelete', - SERVER_UPDATE = 'serverUpdate', - SERVER_CREATE = 'serverCreate', - MESSAGE_DELETE = 'messageDelete', - MESSAGE_UPDATE = 'messageUpdate', - USER_UPDATE = 'userUpdate', - SERVER_MEMBER_JOIN = 'serverMemberJoin', - CHANNEL_UPDATE = 'channelUpdate', - SERVER_MEMBER_LEAVE = 'serverMemberLeave', - SERVER_MEMBER_UPDATE = 'serverMemberUpdate', - ROLE_CREATE = 'roleCreate', - ROLE_DELETE = 'roleDelete', - TYPING_START = 'typingStart', - TYPING_STOP = 'typingStop', - GROUP_JOIN = 'groupJoin', - GROUP_LEAVE = 'groupLeave' -} - -export enum WSEvents { - AUTHENTICATE = 'Authenticate', - AUTHENTICATED = 'Authenticated', - BEGIN_TYPING = 'BeginTyping', - CHANNEL_ACK = 'ChannelAck', - CHANNEL_CREATE = 'ChannelCreate', - CHANNEL_DELETE = 'ChannelDelete', - CHANNEL_GROUP_JOIN = 'ChannelGroupJoin', - CHANNEL_GROUP_LEAVE = 'ChannelGroupLeave', - CHANNEL_START_TYPING = 'ChannelStartTyping', - CHANNEL_STOP_TYPING = 'ChannelStopTyping', - CHANNEL_UPDATE = 'ChannelUpdate', - END_TYPING = 'EndTyping', - ERROR = 'Error', - MESSAGE = 'Message', - MESSAGE_DELETE = 'MessageDelete', - MESSAGE_UPDATE = 'MessageUpdate', - PING = 'Ping', - PONG = 'Pong', - READY = 'Ready', - SERVER_DELETE = 'ServerDelete', - SERVER_MEMBER_JOIN = 'ServerMemberJoin', - SERVER_MEMBER_LEAVE = 'ServerMemberLeave', - SERVER_MEMBER_UPDATE = 'ServerMemberUpdate', - SERVER_ROLE_DELETE = 'ServerRoleDelete', - SERVER_ROLE_UPDATE = 'ServerRoleUpdate', - SERVER_UPDATE = 'ServerUpdate', - USER_RELATIONSHIP = 'UserRelationship', - USER_UPDATE = 'UserUpdate' -} - -export enum Presence { - ONLINE = 'ONLINE', - IDLE = 'IDLE', - BUSY = 'DND', - INVISIBLE = 'OFFLINE' -} - -export enum ChannelTypes { - DM = 'DM', - GROUP = 'GROUP', - TEXT = 'TEXT', - VOICE = 'VOICE', - NOTES = 'NOTES' -} - -export const DEFAULT_CLIENT_OPTIONS: BaseClientOptions = { - rest: { - url: 'https://api.revolt.chat', - timeout: 15_000, - retries: 3 - }, - endpoints: { - api: 'https://api.revolt.chat', - cdn: 'https://autumn.revolt.chat', - invite: 'https://app.revolt.chat' - }, - ws: { - heartbeat: 3_000 - } -} as const - -export const SYSTEM_USER_ID = '0'.repeat(UUID.TIME_LENGTH + UUID.RANDOM_LENGTH) diff --git a/deno/util/Permissions.ts b/deno/util/Permissions.ts deleted file mode 100644 index fc69dda..0000000 --- a/deno/util/Permissions.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { BitField } from './BitField.ts' - -export type ChannelPermissionsString = keyof typeof FLAGS['CHANNEL'] -export type UserPermissionsString = keyof typeof FLAGS['USER'] -export type ServerPermissionsString = keyof typeof FLAGS['SERVER'] -export type ChannelPermissionsResolvable = number | ChannelPermissionsString | ChannelPermissions | ChannelPermissionsResolvable[] -export type UserPermissionsResolvable = number | UserPermissionsString | UserPermissions | UserPermissionsResolvable[] -export type ServerPermissionsResolvable = number | ServerPermissionsString | ServerPermissions | ServerPermissionsResolvable[] - -export declare interface ServerPermissions { - serialize(): Record - any(bit: ServerPermissionsResolvable): boolean - add(...bits: ServerPermissionsResolvable[]): this - remove(...bits: ServerPermissionsResolvable[]): this - has(bit: ServerPermissionsResolvable): boolean -} - -export declare interface ChannelPermissions { - serialize(): Record - any(bit: ChannelPermissionsResolvable): boolean - add(...bits: ChannelPermissionsResolvable[]): this - remove(...bits: ChannelPermissionsResolvable[]): this - has(bit: ChannelPermissionsResolvable): boolean -} - -export declare interface UserPermissions { - serialize(): Record - any(bit: UserPermissionsResolvable): boolean - add(...bits: UserPermissionsResolvable[]): this - remove(...bits: UserPermissionsResolvable[]): this - has(bit: UserPermissionsResolvable): boolean -} - -const FLAGS = { - CHANNEL: { - VIEW_CHANNEL: 1 << 0, - SEND_MESSAGE: 1 << 1, - MANAGE_MESSAGE: 1 << 2, - MANAGE_CHANNEL: 1 << 3, - VOICE_CALL: 1 << 4, - INVITE_OTHERS: 1 << 5, - EMBED_LINKS: 1 << 6, - UPLOAD_FILES: 1 << 7 - }, - USER: { - ACCESS: 1 << 0, - VIEW_PROFILE: 1 << 1, - SEND_MESSAGES: 1 << 2, - INVITE: 1 << 3 - }, - SERVER: { - VIEW_SERVER: 1 << 0, - MANAGE_ROLES: 1 << 1, - MANAGE_CHANNELS: 1 << 2, - MANAGE_SERVER: 1 << 3, - KICK_MEMBERS: 1 << 4, - BAN_MEMBERS: 1 << 5, - CHANGE_NICKNAME: 1 << 12, - MANAGE_NICKNAMES: 1 << 13, - CHANGE_AVATAR: 1 << 14, - REMOVE_AVATARS: 1 << 15 - } -} as const - -export class ChannelPermissions extends BitField { - static FLAGS: typeof FLAGS['CHANNEL'] - constructor(bits?: ChannelPermissionsResolvable) { - super(bits) - } - static resolve(bit: ChannelPermissionsResolvable): number { - return super.resolve(bit) - } -} - -ChannelPermissions.FLAGS = FLAGS.CHANNEL - -export class UserPermissions extends BitField { - static FLAGS: typeof FLAGS['USER'] - constructor(bits?: UserPermissionsResolvable) { - super(bits) - } - static resolve(bit: UserPermissionsResolvable): number { - return super.resolve(bit) - } -} - -UserPermissions.FLAGS = FLAGS.USER - -export class ServerPermissions extends BitField { - static FLAGS: typeof FLAGS['SERVER'] - constructor(bits?: ServerPermissionsResolvable) { - super(bits) - } - static resolve(bit: ServerPermissionsResolvable): number { - return super.resolve(bit) - } -} - -ServerPermissions.FLAGS = FLAGS.SERVER - -export const DEFAULT_PERMISSION_DM = new ChannelPermissions([ - 'VIEW_CHANNEL', - 'VIEW_CHANNEL', - 'MANAGE_CHANNEL', - 'VOICE_CALL', - 'EMBED_LINKS', - 'UPLOAD_FILES' -]).freeze() diff --git a/deno/util/UUID.ts b/deno/util/UUID.ts deleted file mode 100644 index 7e95650..0000000 --- a/deno/util/UUID.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { randomBytes } from 'https://deno.land/std@0.132.0/node/crypto.ts' - -export class UUID extends null { - static readonly ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' - static readonly ENCODING_LENGTH = UUID.ENCODING.length - static readonly RANDOM_LENGTH = 16 - static readonly TIME_LENGTH = 10 - static readonly TIME_MAX = Math.pow(2, 48) - 1 - static get PROG(): number { - return randomBytes(1).readUInt8() / 0xff - } - - private static time(now = Date.now()): string { - let mod: number, - result = '' - - for (let i = this.TIME_LENGTH; i > 0; i--) { - mod = now % this.ENCODING_LENGTH - result = this.ENCODING.charAt(mod) + result - now = (now - mod) / this.ENCODING_LENGTH - } - - return result - } - - private static hash(): string { - let result = '' - - for (let i = this.RANDOM_LENGTH; i > 0; i--) { - let random = Math.floor(this.PROG * this.ENCODING_LENGTH) - - if (random === this.ENCODING_LENGTH) { - random = this.ENCODING_LENGTH - 1 - } - - result = this.ENCODING.charAt(random) + result - } - - return result - } - - static generate(timestamp = Date.now()): string { - return this.time(timestamp) + this.hash() - } - - static timestampOf(id: string): Date { - const timestamp = id - .slice(0, this.TIME_LENGTH) - .split('') - .reverse() - .reduce((carry, char, index) => { - const encodingIndex = this.ENCODING.indexOf(char) - - if (encodingIndex === -1) { - throw new Error('invalid character found: ' + char) - } - - return (carry += encodingIndex * Math.pow(this.ENCODING_LENGTH, index)) - }, 0) - - return new Date(timestamp) - } -} diff --git a/deno/util/index.ts b/deno/util/index.ts deleted file mode 100644 index 4df616c..0000000 --- a/deno/util/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './Badges.ts' -export * from './BitField.ts' -export * from './Collection.ts' -export * from './Constants.ts' -export * from './Permissions.ts' -export * from './UUID.ts' diff --git a/examples/avatar.ts b/examples/avatar.ts index 1f860e5..eccf15d 100644 --- a/examples/avatar.ts +++ b/examples/avatar.ts @@ -1,16 +1,16 @@ -import { Client } from 'better-revolt-js' +import { Client } from 'revolt.io'; -const client = new Client() +const client = new Client(); -client.login('BOT_TOKEN_HERE') +client.login('BOT_TOKEN_HERE'); client.on('ready', () => { - console.log('Ready!') -}) + console.log('Ready!'); +}); -client.on('message', msg => { - if (msg.content === '!avatar') { - const user = msg.mentions.users.first() || msg.author - msg.reply(`[Avatar](${user.displayAvatarURL()})`) - } -}) +client.on('message', (msg) => { + if (msg.content === '!avatar') { + const user = msg.mentions.users.first() || msg.author; + msg.reply(`[Avatar](${user.displayAvatarURL()})`); + } +}); diff --git a/examples/moderation.ts b/examples/moderation.ts index e70066c..e79b214 100644 --- a/examples/moderation.ts +++ b/examples/moderation.ts @@ -1,53 +1,53 @@ -import { Client } from 'better-revolt-js' +import { Client } from 'revolt.io'; -const client = new Client() -const prefix = '!' +const client = new Client(); +const prefix = '!'; -client.login('BOT_TOKEN_HERE') +client.login('BOT_TOKEN_HERE'); client.on('ready', () => { - console.log('Ready!') -}) + console.log('Ready!'); +}); -client.on('message', async msg => { - if (!msg.channel.inServer() || msg.author.bot) return - if (!msg.content.startsWith(prefix)) return +client.on('message', async (msg) => { + if (!msg.channel.inServer() || msg.author.bot) return; + if (!msg.content.startsWith(prefix)) return; - const [command, ...args] = msg.content.slice(prefix.length).trim().split(/ /) + const [command, ...args] = msg.content.slice(prefix.length).trim().split(/ /); - const getMember = () => { - const user = msg.mentions.users.first() - // Server members are not cached by default - return msg.server.members.fetch(user).catch(() => null) - } + const getMember = () => { + const user = msg.mentions.users.first(); + // Server members are not cached by default + return msg.server.members.fetch(user).catch(() => null); + }; - if (command === 'kick') { - const member = await getMember() + if (command === 'kick') { + const member = await getMember(); - if (!member) return msg.reply('Please mention someone first.') + if (!member) return msg.reply('Please mention someone first.'); - await member.kick() + await member.kick(); - msg.reply(`**${member.user.username}** has been kicked`) - } + msg.reply(`**${member.user.username}** has been kicked`); + } - if (command === 'ban') { - const member = await getMember() + if (command === 'ban') { + const member = await getMember(); - if (!member) return msg.reply('Please mention someone first.') + if (!member) return msg.reply('Please mention someone first.'); - await member.ban() + await member.ban(); - msg.reply(`**${member.user.username}** has been banned`) - } + msg.reply(`**${member.user.username}** has been banned`); + } - if (command === 'warn') { - const member = await getMember() + if (command === 'warn') { + const member = await getMember(); - if (!member) return msg.reply('Please mention someone first.') + if (!member) return msg.reply('Please mention someone first.'); - const reason = args.join(' ') || 'No reason' + const reason = args.join(' ') || 'No reason'; - msg.channel.send(`${member}, You have been warned for **${reason}**`) - } -}) + msg.channel.send(`${member}, You have been warned for **${reason}**`); + } +}); diff --git a/examples/ping-pong.ts b/examples/ping-pong.ts index 5331d41..da156f3 100644 --- a/examples/ping-pong.ts +++ b/examples/ping-pong.ts @@ -1,15 +1,15 @@ -import { Client } from 'better-revolt-js' +import { Client } from 'revolt.io'; -const client = new Client() +const client = new Client(); -client.login('BOT_TOKEN_HERE') +client.login('BOT_TOKEN_HERE'); client.on('ready', () => { - console.log('Ready!') -}) - -client.on('message', msg => { - if (msg.content === '!ping') { - msg.reply('Pong!') - } -}) + console.log('Ready!'); +}); + +client.on('message', (msg) => { + if (msg.content === '!ping') { + msg.reply('Pong!'); + } +}); diff --git a/mod.ts b/mod.ts new file mode 100644 index 0000000..ad1171c --- /dev/null +++ b/mod.ts @@ -0,0 +1 @@ +export * from './src/lib.ts' \ No newline at end of file diff --git a/package.json b/package.json deleted file mode 100644 index efa4144..0000000 --- a/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "revolt.io", - "description": "A NodeJS & Deno Revolt library", - "version": "1.0.3", - "scripts": { - "build": "tsc-esm", - "build:deno": "node transpile.deno.js", - "test": "npm run test:types && npm run lint", - "test:types": "tsc --noEmit && echo 'All specs passed validation. You are ready to push!'", - "lint": "eslint src", - "lint:fix": "eslint src --fix", - "format": "prettier --write src/**/*.ts", - "docs": "typedoc --readme README.md src/" - }, - "main": "dist/index.js", - "type": "module", - "dependencies": { - "@discordjs/collection": "^0.6.0", - "node-fetch": "^3.2.4", - "ws": "^8.6.0" - }, - "devDependencies": { - "@digitak/tsc-esm": "^3.1.2", - "@types/node": "16.9.x", - "@types/node-fetch": "^2.6.1", - "@types/ws": "^8.5.3", - "@typescript-eslint/eslint-plugin": "^5.26.0", - "@typescript-eslint/parser": "^5.26.0", - "eslint": "^8.16.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.24.0", - "eslint-plugin-prettier": "^3.4.0", - "prettier": "^2.6.2", - "revolt-api": "0.5.3-5-patch.3", - "typedoc": "^0.22.15", - "typescript": "^4.7.2" - }, - "files": [ - "dist/*" - ], - "license": "Apache-2", - "repository": { - "type": "git", - "url": "https://github.com/revolt-io/revolt.io" - }, - "keywords": [ - "revolt", - "revoltchat", - "api", - "bot", - "node" - ], - "bugs": { - "url": "https://github.com/revolt-io/revolt.io/issues" - }, - "engines": { - "node": ">=16.6.0", - "npm": ">=7.0.0" - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index d490491..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,1786 +0,0 @@ -lockfileVersion: 5.4 - -specifiers: - '@digitak/tsc-esm': ^3.1.2 - '@discordjs/collection': ^0.6.0 - '@types/node': 16.9.x - '@types/node-fetch': ^2.6.1 - '@types/ws': ^8.5.3 - '@typescript-eslint/eslint-plugin': ^5.26.0 - '@typescript-eslint/parser': ^5.26.0 - eslint: ^8.16.0 - eslint-config-prettier: ^8.3.0 - eslint-plugin-import: ^2.24.0 - eslint-plugin-prettier: ^3.4.0 - node-fetch: ^3.2.4 - prettier: ^2.6.2 - revolt-api: 0.5.3-5-patch.3 - typedoc: ^0.22.15 - typescript: ^4.7.2 - ws: ^8.6.0 - -dependencies: - '@discordjs/collection': 0.6.0 - node-fetch: 3.2.4 - ws: 8.6.0 - -devDependencies: - '@digitak/tsc-esm': 3.1.2 - '@types/node': 16.9.6 - '@types/node-fetch': 2.6.1 - '@types/ws': 8.5.3 - '@typescript-eslint/eslint-plugin': 5.26.0_hzuh7e2up357pvq3mkokjvu2lq - '@typescript-eslint/parser': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - eslint: 8.16.0 - eslint-config-prettier: 8.5.0_eslint@8.16.0 - eslint-plugin-import: 2.26.0_grfei5yostfimvqdpf73rlhy3e - eslint-plugin-prettier: 3.4.1_j7rsahgqtkecno6yauhsgsglf4 - prettier: 2.6.2 - revolt-api: 0.5.3-5-patch.3 - typedoc: 0.22.15_typescript@4.7.2 - typescript: 4.7.2 - -packages: - - /@digitak/grubber/3.1.1: - resolution: {integrity: sha512-xHpmj3Erk5AA/nKpOJzap23TJSV0MFRTgtciG8XZg0GP0CUwms0g02SQQaKEPCe2mvKVlqfzad3xV4DiHlq2jA==} - dev: true - - /@digitak/tsc-esm/3.1.2: - resolution: {integrity: sha512-9pey4YgsWA5dmE/KFahIvNukRItibNBryzqKnHr72JRBOk4WP1ZFQWzYJA3DzlPgLEzlcR+j4McXZJFl+2NVCA==} - hasBin: true - dependencies: - '@digitak/grubber': 3.1.1 - fast-glob: 3.2.11 - relaxed-json: 1.0.3 - dev: true - - /@discordjs/collection/0.6.0: - resolution: {integrity: sha512-Ieaetb36l0nmAS5X9Upqk4W7euAO6FdXPxn3I8vBAKEcoIzEZI1mcVcPfCfagGJZSgBKpENnAnKkP4GAn+MV8w==} - engines: {node: '>=16.9.0'} - dev: false - - /@eslint/eslintrc/1.3.0: - resolution: {integrity: sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.3.2 - globals: 13.15.0 - ignore: 5.2.0 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/config-array/0.9.5: - resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/object-schema/1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} - dev: true - - /@insertish/oapi/0.1.15: - resolution: {integrity: sha512-2G8eFxrojF651tBoRutQ8CJOw0u8UjYSlw/LQU+xycw5KpXslhWp/KSR86uIFyDIPddwfMCNA91vwHGCFRA63w==} - hasBin: true - dependencies: - typescript: 4.7.2 - optionalDependencies: - axios: 0.26.1 - openapi-typescript: 5.3.0 - transitivePeerDependencies: - - debug - dev: true - - /@nodelib/fs.scandir/2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat/2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk/1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 - dev: true - - /@types/json-schema/7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true - - /@types/json5/0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/node-fetch/2.6.1: - resolution: {integrity: sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==} - dependencies: - '@types/node': 16.11.36 - form-data: 3.0.1 - dev: true - - /@types/node/16.11.36: - resolution: {integrity: sha512-FR5QJe+TaoZ2GsMHkjuwoNabr+UrJNRr2HNOo+r/7vhcuntM6Ee/pRPOnRhhL2XE9OOvX9VLEq+BcXl3VjNoWA==} - dev: true - - /@types/node/16.9.6: - resolution: {integrity: sha512-YHUZhBOMTM3mjFkXVcK+WwAcYmyhe1wL4lfqNtzI0b3qAy7yuSetnM7QJazgE5PFmgVTNGiLOgRFfJMqW7XpSQ==} - dev: true - - /@types/ws/8.5.3: - resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} - dependencies: - '@types/node': 16.11.36 - dev: true - - /@typescript-eslint/eslint-plugin/5.26.0_hzuh7e2up357pvq3mkokjvu2lq: - resolution: {integrity: sha512-oGCmo0PqnRZZndr+KwvvAUvD3kNE4AfyoGCwOZpoCncSh4MVD06JTE8XQa2u9u+NX5CsyZMBTEc2C72zx38eYA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/parser': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - '@typescript-eslint/scope-manager': 5.26.0 - '@typescript-eslint/type-utils': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - '@typescript-eslint/utils': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - debug: 4.3.4 - eslint: 8.16.0 - functional-red-black-tree: 1.0.1 - ignore: 5.2.0 - regexpp: 3.2.0 - semver: 7.3.7 - tsutils: 3.21.0_typescript@4.7.2 - typescript: 4.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser/5.26.0_xztl6dhthcahlo6akmb2bmjmle: - resolution: {integrity: sha512-n/IzU87ttzIdnAH5vQ4BBDnLPly7rC5VnjN3m0xBG82HK6rhRxnCb3w/GyWbNDghPd+NktJqB/wl6+YkzZ5T5Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.26.0 - '@typescript-eslint/types': 5.26.0 - '@typescript-eslint/typescript-estree': 5.26.0_typescript@4.7.2 - debug: 4.3.4 - eslint: 8.16.0 - typescript: 4.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager/5.26.0: - resolution: {integrity: sha512-gVzTJUESuTwiju/7NiTb4c5oqod8xt5GhMbExKsCTp6adU3mya6AGJ4Pl9xC7x2DX9UYFsjImC0mA62BCY22Iw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.26.0 - '@typescript-eslint/visitor-keys': 5.26.0 - dev: true - - /@typescript-eslint/type-utils/5.26.0_xztl6dhthcahlo6akmb2bmjmle: - resolution: {integrity: sha512-7ccbUVWGLmcRDSA1+ADkDBl5fP87EJt0fnijsMFTVHXKGduYMgienC/i3QwoVhDADUAPoytgjbZbCOMj4TY55A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/utils': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - debug: 4.3.4 - eslint: 8.16.0 - tsutils: 3.21.0_typescript@4.7.2 - typescript: 4.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types/5.26.0: - resolution: {integrity: sha512-8794JZFE1RN4XaExLWLI2oSXsVImNkl79PzTOOWt9h0UHROwJedNOD2IJyfL0NbddFllcktGIO2aOu10avQQyA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/typescript-estree/5.26.0_typescript@4.7.2: - resolution: {integrity: sha512-EyGpw6eQDsfD6jIqmXP3rU5oHScZ51tL/cZgFbFBvWuCwrIptl+oueUZzSmLtxFuSOQ9vDcJIs+279gnJkfd1w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.26.0 - '@typescript-eslint/visitor-keys': 5.26.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.3.7 - tsutils: 3.21.0_typescript@4.7.2 - typescript: 4.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils/5.26.0_xztl6dhthcahlo6akmb2bmjmle: - resolution: {integrity: sha512-PJFwcTq2Pt4AMOKfe3zQOdez6InIDOjUJJD3v3LyEtxHGVVRK3Vo7Dd923t/4M9hSH2q2CLvcTdxlLPjcIk3eg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@types/json-schema': 7.0.11 - '@typescript-eslint/scope-manager': 5.26.0 - '@typescript-eslint/types': 5.26.0 - '@typescript-eslint/typescript-estree': 5.26.0_typescript@4.7.2 - eslint: 8.16.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.16.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys/5.26.0: - resolution: {integrity: sha512-wei+ffqHanYDOQgg/fS6Hcar6wAWv0CUPQ3TZzOWd2BLfgP539rb49bwua8WRAs7R6kOSLn82rfEu2ro6Llt8Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.26.0 - eslint-visitor-keys: 3.3.0 - dev: true - - /acorn-jsx/5.3.2_acorn@8.7.1: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.7.1 - dev: true - - /acorn/8.7.1: - resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv/6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-regex/5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true - - /ansi-styles/3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles/4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /argparse/2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /array-includes/3.1.5: - resolution: {integrity: sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - get-intrinsic: 1.1.1 - is-string: 1.0.7 - dev: true - - /array-union/2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array.prototype.flat/1.3.0: - resolution: {integrity: sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - es-shim-unscopables: 1.0.0 - dev: true - - /asynckit/0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /axios/0.26.1: - resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} - dependencies: - follow-redirects: 1.15.0 - transitivePeerDependencies: - - debug - dev: true - - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /brace-expansion/1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion/2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces/3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - - /call-bind/1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} - dependencies: - function-bind: 1.1.1 - get-intrinsic: 1.1.1 - dev: true - - /callsites/3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /chalk/2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk/4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /color-convert/1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert/2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name/1.1.3: - resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=} - dev: true - - /color-name/1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /combined-stream/1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /commander/2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} - dev: true - - /cross-spawn/7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /data-uri-to-buffer/4.0.0: - resolution: {integrity: sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==} - engines: {node: '>= 12'} - dev: false - - /debug/2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug/3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /deep-is/0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /define-properties/1.1.4: - resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==} - engines: {node: '>= 0.4'} - dependencies: - has-property-descriptors: 1.0.0 - object-keys: 1.1.1 - dev: true - - /delayed-stream/1.0.0: - resolution: {integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk=} - engines: {node: '>=0.4.0'} - dev: true - - /dir-glob/3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /doctrine/2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine/3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /es-abstract/1.20.1: - resolution: {integrity: sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - es-to-primitive: 1.2.1 - function-bind: 1.1.1 - function.prototype.name: 1.1.5 - get-intrinsic: 1.1.1 - get-symbol-description: 1.0.0 - has: 1.0.3 - has-property-descriptors: 1.0.0 - has-symbols: 1.0.3 - internal-slot: 1.0.3 - is-callable: 1.2.4 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-weakref: 1.0.2 - object-inspect: 1.12.1 - object-keys: 1.1.1 - object.assign: 4.1.2 - regexp.prototype.flags: 1.4.3 - string.prototype.trimend: 1.0.5 - string.prototype.trimstart: 1.0.5 - unbox-primitive: 1.0.2 - dev: true - - /es-shim-unscopables/1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} - dependencies: - has: 1.0.3 - dev: true - - /es-to-primitive/1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.4 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /escape-string-regexp/1.0.5: - resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp/4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-config-prettier/8.5.0_eslint@8.16.0: - resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.16.0 - dev: true - - /eslint-import-resolver-node/0.3.6: - resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} - dependencies: - debug: 3.2.7 - resolve: 1.22.0 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils/2.7.3_zhgf6mw2wzy6dnrak3ta47vb3m: - resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - debug: 3.2.7 - eslint-import-resolver-node: 0.3.6 - find-up: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-import/2.26.0_grfei5yostfimvqdpf73rlhy3e: - resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.26.0_xztl6dhthcahlo6akmb2bmjmle - array-includes: 3.1.5 - array.prototype.flat: 1.3.0 - debug: 2.6.9 - doctrine: 2.1.0 - eslint: 8.16.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.3_zhgf6mw2wzy6dnrak3ta47vb3m - has: 1.0.3 - is-core-module: 2.9.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.5 - resolve: 1.22.0 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-prettier/3.4.1_j7rsahgqtkecno6yauhsgsglf4: - resolution: {integrity: sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==} - engines: {node: '>=6.0.0'} - peerDependencies: - eslint: '>=5.0.0' - eslint-config-prettier: '*' - prettier: '>=1.13.0' - peerDependenciesMeta: - eslint-config-prettier: - optional: true - dependencies: - eslint: 8.16.0 - eslint-config-prettier: 8.5.0_eslint@8.16.0 - prettier: 2.6.2 - prettier-linter-helpers: 1.0.0 - dev: true - - /eslint-scope/5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope/7.1.1: - resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-utils/3.0.0_eslint@8.16.0: - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.16.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys/2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys/3.3.0: - resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint/8.16.0: - resolution: {integrity: sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint/eslintrc': 1.3.0 - '@humanwhocodes/config-array': 0.9.5 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.16.0 - eslint-visitor-keys: 3.3.0 - espree: 9.3.2 - esquery: 1.4.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - functional-red-black-tree: 1.0.1 - glob-parent: 6.0.2 - globals: 13.15.0 - ignore: 5.2.0 - import-fresh: 3.3.0 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.1 - regexpp: 3.2.0 - strip-ansi: 6.0.1 - strip-json-comments: 3.1.1 - text-table: 0.2.0 - v8-compile-cache: 2.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree/9.3.2: - resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.7.1 - acorn-jsx: 5.3.2_acorn@8.7.1 - eslint-visitor-keys: 3.3.0 - dev: true - - /esquery/1.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse/4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse/4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse/5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils/2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /fast-deep-equal/3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-diff/1.2.0: - resolution: {integrity: sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==} - dev: true - - /fast-glob/3.2.11: - resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - - /fast-json-stable-stringify/2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein/2.0.6: - resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} - dev: true - - /fastq/1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} - dependencies: - reusify: 1.0.4 - dev: true - - /fetch-blob/3.1.5: - resolution: {integrity: sha512-N64ZpKqoLejlrwkIAnb9iLSA3Vx/kjgzpcDhygcqJ2KKjky8nCgUQ+dzXtbrLaWZGZNmNfQTsiQ0weZ1svglHg==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.2.1 - dev: false - - /file-entry-cache/6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /fill-range/7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-up/2.1.0: - resolution: {integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c=} - engines: {node: '>=4'} - dependencies: - locate-path: 2.0.0 - dev: true - - /flat-cache/3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.5 - rimraf: 3.0.2 - dev: true - - /flatted/3.2.5: - resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} - dev: true - - /follow-redirects/1.15.0: - resolution: {integrity: sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: true - - /form-data/3.0.1: - resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /formdata-polyfill/4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.1.5 - dev: false - - /fs.realpath/1.0.0: - resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} - dev: true - - /function-bind/1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true - - /function.prototype.name/1.1.5: - resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - functions-have-names: 1.2.3 - dev: true - - /functional-red-black-tree/1.0.1: - resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} - dev: true - - /functions-have-names/1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /get-intrinsic/1.1.1: - resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} - dependencies: - function-bind: 1.1.1 - has: 1.0.3 - has-symbols: 1.0.3 - dev: true - - /get-symbol-description/1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.1 - dev: true - - /glob-parent/5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent/6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob/7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals/13.15.0: - resolution: {integrity: sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalyzer/0.1.0: - resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} - dev: true - optional: true - - /globby/11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.11 - ignore: 5.2.0 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /globrex/0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - dev: true - optional: true - - /has-bigints/1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag/3.0.0: - resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=} - engines: {node: '>=4'} - dev: true - - /has-flag/4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true - - /has-property-descriptors/1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} - dependencies: - get-intrinsic: 1.1.1 - dev: true - - /has-symbols/1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag/1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /has/1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - dev: true - - /ignore/5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} - engines: {node: '>= 4'} - dev: true - - /import-fresh/3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash/0.1.4: - resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} - engines: {node: '>=0.8.19'} - dev: true - - /inflight/1.0.6: - resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits/2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /internal-slot/1.0.3: - resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.1.1 - has: 1.0.3 - side-channel: 1.0.4 - dev: true - - /is-bigint/1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-boolean-object/1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-callable/1.2.4: - resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module/2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} - dependencies: - has: 1.0.3 - dev: true - - /is-date-object/1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-extglob/2.1.1: - resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} - engines: {node: '>=0.10.0'} - dev: true - - /is-glob/4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-negative-zero/2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object/1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-regex/1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - has-tostringtag: 1.0.0 - dev: true - - /is-shared-array-buffer/1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.2 - dev: true - - /is-string/1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-symbol/1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-weakref/1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.2 - dev: true - - /isexe/2.0.0: - resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} - dev: true - - /js-yaml/4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /json-schema-traverse/0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify/1.0.1: - resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} - dev: true - - /json5/1.0.1: - resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} - hasBin: true - dependencies: - minimist: 1.2.6 - dev: true - - /jsonc-parser/3.0.0: - resolution: {integrity: sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==} - dev: true - - /levn/0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /locate-path/2.0.0: - resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=} - engines: {node: '>=4'} - dependencies: - p-locate: 2.0.0 - path-exists: 3.0.0 - dev: true - - /lodash.defaultsdeep/4.6.1: - resolution: {integrity: sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==} - dev: true - - /lodash.merge/4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lru-cache/6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /lunr/2.3.9: - resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - dev: true - - /marked/4.0.16: - resolution: {integrity: sha512-wahonIQ5Jnyatt2fn8KqF/nIqZM8mh3oRu2+l5EANGMhu6RFjiSG52QNE2eWzFMI94HqYSgN184NurgNG6CztA==} - engines: {node: '>= 12'} - hasBin: true - dev: true - - /merge2/1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micromatch/4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime-db/1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types/2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mime/3.0.0: - resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} - engines: {node: '>=10.0.0'} - hasBin: true - dev: true - optional: true - - /minimatch/3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch/5.1.0: - resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} - dev: true - - /ms/2.0.0: - resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} - dev: true - - /ms/2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms/2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /natural-compare/1.4.0: - resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} - dev: true - - /node-domexception/1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: false - - /node-fetch/3.2.4: - resolution: {integrity: sha512-WvYJRN7mMyOLurFR2YpysQGuwYrJN+qrrpHjJDuKMcSPdfFccRUla/kng2mz6HWSBxJcqPbvatS6Gb4RhOzCJw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.0 - fetch-blob: 3.1.5 - formdata-polyfill: 4.0.10 - dev: false - - /object-inspect/1.12.1: - resolution: {integrity: sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA==} - dev: true - - /object-keys/1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign/4.1.2: - resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.values/1.1.5: - resolution: {integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - dev: true - - /once/1.4.0: - resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} - dependencies: - wrappy: 1.0.2 - dev: true - - /openapi-typescript/5.3.0: - resolution: {integrity: sha512-Y1QI1nWQE56nYFGXMAanS9VVHCUKzgLCfAe43vFbuciqm48N02DX9LWSarX18PGF9qKd6EWhmIlCumOXKPzAug==} - engines: {node: '>= 14.0.0', npm: '>= 7.0.0'} - hasBin: true - requiresBuild: true - dependencies: - js-yaml: 4.1.0 - mime: 3.0.0 - prettier: 2.6.2 - tiny-glob: 0.2.9 - undici: 5.3.0 - yargs-parser: 21.0.1 - dev: true - optional: true - - /optionator/0.9.1: - resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.3 - dev: true - - /p-limit/1.3.0: - resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} - engines: {node: '>=4'} - dependencies: - p-try: 1.0.0 - dev: true - - /p-locate/2.0.0: - resolution: {integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=} - engines: {node: '>=4'} - dependencies: - p-limit: 1.3.0 - dev: true - - /p-try/1.0.0: - resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=} - engines: {node: '>=4'} - dev: true - - /parent-module/1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /path-exists/3.0.0: - resolution: {integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=} - engines: {node: '>=4'} - dev: true - - /path-is-absolute/1.0.1: - resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} - engines: {node: '>=0.10.0'} - dev: true - - /path-key/3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse/1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-type/4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /picomatch/2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /prelude-ls/1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-linter-helpers/1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.2.0 - dev: true - - /prettier/2.6.2: - resolution: {integrity: sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /punycode/2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} - engines: {node: '>=6'} - dev: true - - /queue-microtask/1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /regexp.prototype.flags/1.4.3: - resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - functions-have-names: 1.2.3 - dev: true - - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} - dev: true - - /relaxed-json/1.0.3: - resolution: {integrity: sha512-b7wGPo7o2KE/g7SqkJDDbav6zmrEeP4TK2VpITU72J/M949TLe/23y/ZHJo+pskcGM52xIfFoT9hydwmgr1AEg==} - engines: {node: '>= 0.10.0'} - hasBin: true - dependencies: - chalk: 2.4.2 - commander: 2.20.3 - dev: true - - /resolve-from/4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve/1.22.0: - resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} - hasBin: true - dependencies: - is-core-module: 2.9.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /reusify/1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /revolt-api/0.5.3-5-patch.3: - resolution: {integrity: sha512-xESgQ9kp8T5iupeixt/yJIiGDiM11pm1b2E6srM/+jrV7Jyrj/vPgDPv3hEeJFhNmUK6EP5tKxkmTBhcqNE/Vw==} - dependencies: - '@insertish/oapi': 0.1.15 - axios: 0.26.1 - lodash.defaultsdeep: 4.6.1 - transitivePeerDependencies: - - debug - dev: true - - /rimraf/3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /run-parallel/1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /semver/7.3.7: - resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /shebang-command/2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex/3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shiki/0.10.1: - resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==} - dependencies: - jsonc-parser: 3.0.0 - vscode-oniguruma: 1.6.2 - vscode-textmate: 5.2.0 - dev: true - - /side-channel/1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.1.1 - object-inspect: 1.12.1 - dev: true - - /slash/3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /string.prototype.trimend/1.0.5: - resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - dev: true - - /string.prototype.trimstart/1.0.5: - resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} - dependencies: - call-bind: 1.0.2 - define-properties: 1.1.4 - es-abstract: 1.20.1 - dev: true - - /strip-ansi/6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - - /strip-bom/3.0.0: - resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=} - engines: {node: '>=4'} - dev: true - - /strip-json-comments/3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color/5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color/7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-preserve-symlinks-flag/1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /text-table/0.2.0: - resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} - dev: true - - /tiny-glob/0.2.9: - resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} - dependencies: - globalyzer: 0.1.0 - globrex: 0.1.2 - dev: true - optional: true - - /to-regex-range/5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /tsconfig-paths/3.14.1: - resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.1 - minimist: 1.2.6 - strip-bom: 3.0.0 - dev: true - - /tslib/1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tsutils/3.21.0_typescript@4.7.2: - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 4.7.2 - dev: true - - /type-check/0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest/0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /typedoc/0.22.15_typescript@4.7.2: - resolution: {integrity: sha512-CMd1lrqQbFvbx6S9G6fL4HKp3GoIuhujJReWqlIvSb2T26vGai+8Os3Mde7Pn832pXYemd9BMuuYWhFpL5st0Q==} - engines: {node: '>= 12.10.0'} - hasBin: true - peerDependencies: - typescript: 4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x - dependencies: - glob: 7.2.3 - lunr: 2.3.9 - marked: 4.0.16 - minimatch: 5.1.0 - shiki: 0.10.1 - typescript: 4.7.2 - dev: true - - /typescript/4.7.2: - resolution: {integrity: sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: true - - /unbox-primitive/1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.2 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici/5.3.0: - resolution: {integrity: sha512-8LxC/xmR2GCE4q1heE1sJxVnnf5S6yQ2dObvMFBBWkB8aQlaqNuWovgRFWRMB7KUdLPGZfOTTmUeeLEJYX56iQ==} - engines: {node: '>=12.18'} - dev: true - optional: true - - /uri-js/4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.1.1 - dev: true - - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true - - /vscode-oniguruma/1.6.2: - resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} - dev: true - - /vscode-textmate/5.2.0: - resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} - dev: true - - /web-streams-polyfill/3.2.1: - resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} - engines: {node: '>= 8'} - dev: false - - /which-boxed-primitive/1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which/2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: true - - /wrappy/1.0.2: - resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} - dev: true - - /ws/8.6.0: - resolution: {integrity: sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==} - 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 - dev: false - - /yallist/4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yargs-parser/21.0.1: - resolution: {integrity: sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==} - engines: {node: '>=12'} - dev: true - optional: true diff --git a/scripts/build_npm.ts b/scripts/build_npm.ts new file mode 100644 index 0000000..1641af0 --- /dev/null +++ b/scripts/build_npm.ts @@ -0,0 +1,75 @@ +import { build, emptyDir } from 'https://deno.land/x/dnt@0.23.0/mod.ts'; + +if (!Deno.args[0]) { + console.log('Missing version'); + Deno.exit(); +} + +await emptyDir('./npm'); + +await build({ + test: false, + packageManager: 'pnpm', + scriptModule: false, + entryPoints: ['./mod.ts'], + outDir: './npm', + shims: { + webSocket: true, + custom: [{ + package: { + name: 'crypto', + }, + globalNames: ['randomBytes'], + }], + }, + mappings: { + 'https://deno.land/x/revoltio_rest@v1.1.0/mod.ts': { + name: '@revoltio/rest', + version: '^1.1.0', + }, + 'https://esm.sh/@discordjs/collection@0.6.0': { + name: '@discordjs/collection', + version: '^0.6.0', + }, + 'https://deno.land/x/revolt_api@0.4.0/types.ts': { + name: 'revolt-api', + version: '^0.5.3-5-patch.4', + }, + }, + + package: { + name: 'revolt.io', + version: Deno.args[0].replace(/[A-Z]+/gi, ''), + description: 'A NodeJS & Deno Revolt library"', + license: 'Apache-2', + devDependencies: { + '@types/node': '^16', + '@types/ws': '^8.5.3', + 'revolt-api': '^0.5.3-5-patch.4', + }, + repository: { + type: 'git', + url: 'git+https://github.com/revolt-io/revolt.io.git', + }, + bugs: { + url: 'https://github.com/revolt-io/revolt.io/issues', + }, + keywords: [ + 'revolt', + 'revoltchat', + 'api', + 'bot', + 'client', + ], + engines: { + node: '>=16.6.0', + }, + files: [ + 'esm/*', + 'types/*', + ], + }, +}); + +Deno.copyFileSync('LICENSE', 'npm/LICENSE'); +Deno.copyFileSync('README.md', 'npm/README.md'); diff --git a/src/client/BaseClient.ts b/src/client/BaseClient.ts index b99d18a..fc3df55 100644 --- a/src/client/BaseClient.ts +++ b/src/client/BaseClient.ts @@ -1,97 +1,132 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { EventEmitter } from 'events' -import { Client } from '../client/index' -import { REST, Endpoints } from '../rest/index' -import type { Channel, DMChannel, GroupChannel, Role, ServerMember, TextChannel, User, Server, Message } from '../structures/index' -import { DEFAULT_CLIENT_OPTIONS, Events } from '../util/Constants' +// deno-lint-ignore-file no-explicit-any +import { EventEmitter } from 'https://deno.land/std@0.132.0/node/events.ts'; +import { Client } from './mod.ts'; +import { + REST, + RESTOptions, +} from 'https://deno.land/x/revoltio_rest@v1.1.0/mod.ts'; +import type { + Channel, + DMChannel, + GroupChannel, + Message, + Role, + Server, + ServerMember, + TextChannel, + User, +} from '../structures/mod.ts'; +import { DEFAULT_CLIENT_OPTIONS, Events } from '../util/Constants.ts'; export interface ClientEvents { - message: [Message] - messageDelete: [Message] - messageUpdate: [Message, Message] - ready: [Client] - serverCreate: [Server] - serverDelete: [Server] - serverUpdate: [Server, Server] - debug: [string] - error: [unknown] - raw: [unknown] - userUpdate: [User, User] - serverMemberJoin: [ServerMember] - channelUpdate: [Channel, Channel] - serverMemberLeave: [ServerMember] - serverMemberUpdate: [ServerMember, ServerMember] - roleDelete: [Role] - typingStart: [TextChannel | DMChannel | GroupChannel, User] - typingStop: [TextChannel | DMChannel | GroupChannel, User] - groupJoin: [GroupChannel, User] - groupLeave: [GroupChannel, User] + message: [Message]; + messageDelete: [Message]; + messageUpdate: [Message, Message]; + ready: [Client]; + serverCreate: [Server]; + serverDelete: [Server]; + serverUpdate: [Server, Server]; + debug: [string]; + error: [unknown]; + raw: [unknown]; + userUpdate: [User, User]; + serverMemberJoin: [ServerMember]; + channelUpdate: [Channel, Channel]; + serverMemberLeave: [ServerMember]; + serverMemberUpdate: [ServerMember, ServerMember]; + roleDelete: [Role]; + typingStart: [TextChannel | DMChannel | GroupChannel, User]; + typingStop: [TextChannel | DMChannel | GroupChannel, User]; + groupJoin: [GroupChannel, User]; + groupLeave: [GroupChannel, User]; } export declare interface BaseClient { - on(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - on(event: Exclude, listener: (...args: any[]) => Awaited): this - once(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - once(event: Exclude, listener: (...args: any[]) => Awaited): this - emit(event: K, ...args: ClientEvents[K]): boolean - emit(event: Exclude, ...args: unknown[]): boolean - off(event: K, listener: (...args: ClientEvents[K]) => Awaited): this - off(event: Exclude, listener: (...args: any[]) => Awaited): this - removeAllListeners(event?: K): this - removeAllListeners(event?: Exclude): this + on( + event: K, + listener: (...args: ClientEvents[K]) => Awaited, + ): this; + on( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + once( + event: K, + listener: (...args: ClientEvents[K]) => Awaited, + ): this; + once( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + emit( + event: K, + ...args: ClientEvents[K] + ): boolean; + emit( + event: Exclude, + ...args: unknown[] + ): boolean; + off( + event: K, + listener: (...args: ClientEvents[K]) => Awaited, + ): this; + off( + event: Exclude, + listener: (...args: any[]) => Awaited, + ): this; + removeAllListeners(event?: K): this; + removeAllListeners( + event?: Exclude, + ): this; } export interface BaseClientOptions { - rest: { - url: string - retries: number - timeout: number - } - endpoints: { - cdn: string - invite: string - api: string - } - ws: { - heartbeat: number - } + rest: RESTOptions; + ws: { + heartbeat: number; + }; } -type DeepPartial = T extends object - ? { - [P in keyof T]?: DeepPartial - } - : T +// deno-lint-ignore ban-types +type DeepPartial = T extends object ? { + [P in keyof T]?: DeepPartial; +} + : T; export function isObject(item: unknown) { - return item && typeof item === 'object' && !Array.isArray(item) + return item && typeof item === 'object' && !Array.isArray(item); } export abstract class BaseClient extends EventEmitter { - readonly api: REST - readonly endpoints: Endpoints - #token: string | null = null - bot = true - options = { ...DEFAULT_CLIENT_OPTIONS } - - constructor(opts: DeepPartial = {}) { - super() + readonly api: REST; + #token: string | null = null; + bot = true; + options = { ...DEFAULT_CLIENT_OPTIONS }; - for (const key in opts) { - Object.assign(this.options[key as keyof BaseClientOptions], opts[key as keyof BaseClientOptions]) - } + constructor(opts: DeepPartial = {}) { + super(); - this.api = new REST(this.options.rest) - this.endpoints = new Endpoints(this.options.endpoints) - this.api.debug = (msg: string) => this.emit(Events.DEBUG, msg) + for (const key in opts) { + Object.assign( + this.options[key as keyof BaseClientOptions], + opts[key as keyof BaseClientOptions], + ); } - set token(token: string | null) { - this.#token = token - this.api.setToken(token, this.bot) - } + this.api = new REST(this.options.rest); + this.api.debug = (msg: string) => this.emit(Events.DEBUG, `[HTTP]: ${msg}`); + } - get token() { - return this.#token - } + debug(msg: unknown): void { + this.emit(Events.DEBUG, `[MAIN]: ${msg}`); + } + + set token(token: string | null) { + this.#token = token; + this.api.setToken(token, this.bot); + } + + get token() { + return this.#token; + } } diff --git a/src/client/Client.ts b/src/client/Client.ts index fe34c8f..edfa8bb 100644 --- a/src/client/Client.ts +++ b/src/client/Client.ts @@ -1,63 +1,57 @@ -import type { RevoltConfig } from 'revolt-api' -import { BaseClient, WebSocketShard } from './index' -import { ActionManager } from './actions/ActionManager' -import { Error } from '../errors/index' -import { ChannelManager, ServerManager, UserManager } from '../managers/index' -import { ClientUser } from '../structures/index' -import { Events } from '../util/Constants' +import type { RevoltConfig } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseClient, WebSocketShard } from './mod.ts'; +import { ActionManager } from './actions/ActionManager.ts'; +import { Error } from '../errors/mod.ts'; +import { ChannelManager, ServerManager, UserManager } from '../managers/mod.ts'; +import { ClientUser } from '../structures/mod.ts'; export class Client extends BaseClient { - protected readonly ws = new WebSocketShard(this) - readonly actions = new ActionManager(this) - readonly channels = new ChannelManager(this) - readonly servers = new ServerManager(this) - readonly users = new UserManager(this) - user: ClientUser | null = null - configuration?: RevoltConfig - readyAt: Date | null = null - - get readyTimestamp(): number | null { - return this.readyAt?.getTime() ?? null + protected readonly ws = new WebSocketShard(this); + readonly actions = new ActionManager(this); + readonly channels = new ChannelManager(this); + readonly servers = new ServerManager(this); + readonly users = new UserManager(this); + user: ClientUser | null = null; + configuration?: RevoltConfig; + readyAt: Date | null = null; + + get readyTimestamp(): number | null { + return this.readyAt?.getTime() ?? null; + } + + get uptime(): number | null { + return this.readyAt ? Date.now() - this.readyAt.getTime() : null; + } + + async login(token?: string, type: 'user' | 'bot' = 'bot'): Promise { + if (!token) throw new Error('INVALID_TOKEN'); + + this.bot = type.toLowerCase() === 'bot'; + this.token = token ?? null; + + this.debug('Fetch configuration...'); + this.configuration = await this.api.get('/'); + + this.debug('Preparing to connect to the gateway...'); + + try { + await this.ws.connect(); + } catch (err) { + await this.destroy(); + throw err; } - get uptime(): number | null { - return this.readyAt ? Date.now() - this.readyAt.getTime() : null - } - - async login(token?: string, type: 'user' | 'bot' = 'bot'): Promise { - if (!token) throw new Error('INVALID_TOKEN') - - this.debug('Fetch configuration...') - - this.configuration = await this.api.get('/') - this.bot = type.toLowerCase() === 'bot' - this.token = token ?? null - - this.debug('Preparing to connect to the gateway...') - - try { - await this.ws.connect() - } catch (err) { - await this.destroy() - throw err - } + this.readyAt = new Date(); + } - this.readyAt = new Date() - } - - async destroy(): Promise { - this.token = null - this.user = null - this.readyAt = null - this.api.setToken(null) - await this.ws.destroy() - } + async destroy(): Promise { + this.token = null; + this.user = null; + this.readyAt = null; + await this.ws.destroy(); + } - private debug(message: string): void { - this.emit(Events.DEBUG, message) - } - - isReady(): boolean { - return this.readyAt != null - } + isReady(): boolean { + return this.readyAt != null; + } } diff --git a/src/client/WebSocket.ts b/src/client/WebSocket.ts index 9f43e73..a7f798d 100644 --- a/src/client/WebSocket.ts +++ b/src/client/WebSocket.ts @@ -1,192 +1,221 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import WebSocket from 'ws' -import type { Client } from './Client' -import { ClientUser } from '../structures/index' -import { Events, WSEvents } from '../util/index' +// deno-lint-ignore-file no-explicit-any +import type { Client } from './Client.ts'; +import { ClientUser } from '../structures/mod.ts'; +import { Events, WSEvents } from '../util/mod.ts'; +import { Error } from '../errors/mod.ts'; + +declare function clearInterval(id: number): void; +declare function setInterval( + cb: (...args: any[]) => void, + delay?: number, + ...args: any[] +): number; export class WebSocketShard { - heartbeatInterval?: NodeJS.Timer - lastPingTimestamp?: number - lastPongAcked = false - socket: WebSocket | null = null - connected = false - ready = false - - constructor(protected readonly client: Client) {} - - send(data: unknown): Promise { - return new Promise(resolve => { - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.send(JSON.stringify(data)) - resolve() - } else { - this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`) - resolve() - } - }) + heartbeatInterval?: number; + lastPingTimestamp?: number; + lastPongAcked = false; + socket: WebSocket | null = null; + connected = false; + ready = false; + reconnecting: Promise | null = null; + + constructor(protected readonly client: Client) {} + + private debug(message: unknown): void { + this.client.emit(Events.DEBUG, `[WS]: ${message}`); + } + + async send(data: unknown): Promise { + if (this.reconnecting) { + this.debug('Waiting reconnecting...'); + await this.reconnecting; } - private async onOpen(): Promise { - await this.send({ - type: WSEvents.AUTHENTICATE, - token: this.client.token - }) + if (this.socket?.readyState === WebSocket.OPEN) { + this.socket.send(JSON.stringify(data)); + } else { + this.debug( + `Tried to send packet '${ + JSON.stringify(data) + }' but no WebSocket is available!`, + ); } - - private debug(message: unknown): void { - this.client.emit(Events.DEBUG, `[WS]: ${message}`) + } + + private onOpen(): void { + if (!this.client.token) throw new Error('INVALID_TOKEN'); + this.send({ + type: WSEvents.AUTHENTICATE, + token: this.client.token, + }); + } + + get ping(): number { + if (!this.lastPingTimestamp) return -0; + return Date.now() - this.lastPingTimestamp; + } + + setHeartbeatTimer(time: number): void { + this.debug(`Setting a heartbeat interval for ${time}ms.`); + + if (this.heartbeatInterval) clearInterval(this.heartbeatInterval); + if (time !== -1) { + this.heartbeatInterval = setInterval(() => this.sendHeartbeat(), time); } + } + + sendHeartbeat(): void { + this.debug('Sending a heartbeat.'); - get ping(): number { - if (!this.lastPingTimestamp) return -0 - return Date.now() - this.lastPingTimestamp + if (!this.lastPongAcked) { + this.debug('Did not receive a pong ack last time.'); + this.debug('Reconnecting...'); + this.reconnecting = this.destroy().then(() => this.connect()).then(() => + this.reconnecting = null + ); } - setHeartbeatTimer(time: number): void { - this.debug(`Setting a heartbeat interval for ${time}ms.`) + const now = Date.now(); + this.send({ type: WSEvents.PING, data: now }); + this.lastPongAcked = false; + this.lastPingTimestamp = now; + } - if (this.heartbeatInterval) clearInterval(this.heartbeatInterval) + private onError(event: unknown): void { + this.client.emit(Events.ERROR, event); + } - if (time !== -1) { - this.heartbeatInterval = setInterval(() => this.sendHeartbeat(), time) - } + private onMessage({ data }: { data: unknown }): void { + let packet: unknown; + + try { + packet = JSON.parse(String(data)); + } catch (err) { + this.client.emit(Events.ERROR, err); + return; } - sendHeartbeat(skip = false): void { - if (!skip && !this.lastPongAcked) { - this.debug('Did not receive a pong ack last time.') - } + this.client.emit(Events.RAW, packet); - const now = Date.now() + this.onPacket(packet); + } - this.debug('Sending a heartbeat.') - this.send({ type: WSEvents.PING, data: now }) - this.lastPongAcked = false - this.lastPingTimestamp = now - } + private onClose(event: { code: number; reason: string }): void { + this.debug(`Closed with reason: ${event.reason}, code: ${event.code}`); + this.destroy(); + } - private onError(event: ErrorEvent | Event): void { - this.client.emit(Events.ERROR, event) + private onPacket(packet: any) { + if (!packet) { + this.debug(`Received broken packet: '${packet}'.`); + return; } - private onMessage({ data }: MessageEvent): void { - let packet: unknown + switch (packet.type) { + case WSEvents.BULK: + console.log(packet); + for (const p of packet.v) this.onPacket(p); + break; + case WSEvents.AUTHENTICATED: + this.connected = true; + break; + case WSEvents.PONG: + this.debug(`Received a heartbeat.`); + this.lastPongAcked = true; + break; + case WSEvents.ERROR: + this.client.emit(Events.ERROR, packet.error); + break; + case WSEvents.READY: + this.lastPongAcked = true; + + for (const user of packet.users) { + this.client.users._add(user); + if (user.relationship === 'User' && !this.client.user) { + const clientUser = + (this.client.user = new ClientUser(this.client, user)); + this.client.users.cache.set(clientUser.id, clientUser); + } + } - try { - packet = JSON.parse(data as unknown as string) - } catch (err) { - this.client.emit(Events.ERROR, err) - return + for (const server of packet.servers) { + this.client.servers._add(server); } - this.client.emit(Events.RAW, packet) + for (const channel of packet.channels) { + this.client.channels._add(channel); + } - this.onPacket(packet) - } + for (const member of packet.members) { + this.client.servers.cache.get(member._id.server)?.members._add( + member, + ); + } - private onClose(event: CloseEvent): void { - this.debug(`[WS] Closed with reason: ${event.reason}, code: ${event.code}`) - this.destroy() - } + this.setHeartbeatTimer(this.client.options.ws.heartbeat); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private onPacket(packet: any) { - if (!packet) { - this.debug(`Received broken packet: '${packet}'.`) - return - } + this.ready = true; - switch (packet.type) { - case WSEvents.AUTHENTICATED: - this.connected = true - break - case WSEvents.PONG: - this.lastPongAcked = true - break - case WSEvents.ERROR: - this.client.emit(Events.ERROR, packet.error) - break - case WSEvents.READY: - this.lastPongAcked = true - - for (const user of packet.users) { - this.client.users._add(user) - if (user.relationship === 'User' && !this.client.user) { - const clientUser = (this.client.user = new ClientUser(this.client, user)) - this.client.users.cache.set(clientUser.id, clientUser) - } - } - - for (const server of packet.servers) { - this.client.servers._add(server) - } - - for (const channel of packet.channels) { - this.client.channels._add(channel) - } - - for (const member of packet.members) { - this.client.servers.cache.get(member._id.server)?.members._add(member) - } - - this.setHeartbeatTimer(this.client.options.ws.heartbeat) - - this.ready = true - - this.client.emit(Events.READY, this.client) - - break - default: { - const action = this.client.actions.get(packet.type) - - if (action) { - action.handle(packet) - } else { - this.debug(`Received unknown packet "${packet.type}"`) - } - - break - } - } - } + this.client.emit(Events.READY, this.client); - connect(): Promise { - return new Promise(resolve => { - if (this.socket?.readyState === WebSocket.OPEN && this.ready) { - return resolve(this) - } - - if (typeof this.client.configuration === 'undefined') { - throw new Error('Attempted to open WebSocket without syncing configuration from server.') - } - - if (typeof this.client.token !== 'string') { - throw new Error('Attempted to open WebSocket without valid token.') - } - - const ws = (this.socket = this.socket ?? new WebSocket(this.client.configuration.ws)) - - // NOTE: Don't remove the 'any' they are requires to work with deno - ws.onopen = this.onOpen.bind(this) as any - ws.onmessage = this.onMessage.bind(this) as any - ws.onerror = this.onError.bind(this) as any - ws.onclose = this.onClose.bind(this) as any - ws.addEventListener('open', () => resolve(this)) - }) - } + break; + default: { + const action = this.client.actions.get(packet.type); + + if (action) { + action.handle(packet); + } else { + this.debug(`Received unknown packet "${packet.type}"`); + } - destroy(): Promise { - return new Promise(resolve => { - this.setHeartbeatTimer(-1) - this.connected = false - this.ready = false - - if (this.socket?.readyState === WebSocket.OPEN) { - this.socket.addEventListener('close', () => resolve(this)) - this.socket.close() - } else { - resolve(this) - } - }) + break; + } } + } + + connect(): Promise { + return new Promise((resolve) => { + if (this.socket?.readyState === WebSocket.OPEN && this.ready) { + return resolve(this); + } + + if (typeof this.client.configuration === 'undefined') { + throw new Error('MISSING_CONFIGURATION_SYNC'); + } + + if (typeof this.client.token !== 'string') { + throw new Error('INVALID_TOKEN'); + } + + const ws = (this.socket = this.socket ?? + new WebSocket(this.client.configuration.ws)); + + ws.onopen = this.onOpen.bind(this); + ws.onmessage = this.onMessage.bind(this); + ws.onerror = this.onError.bind(this); + ws.onclose = this.onClose.bind(this); + ws.addEventListener('open', () => resolve(this)); + }); + } + + destroy(): Promise { + return new Promise((resolve) => { + this.setHeartbeatTimer(-1); + this.connected = false; + this.ready = false; + + if (this.socket?.readyState === WebSocket.OPEN) { + this.socket.addEventListener('close', () => { + this.socket = null; + resolve(); + }); + + this.socket.close(); + } else { + this.socket = null; + resolve(); + } + }); + } } diff --git a/src/client/actions/Action.ts b/src/client/actions/Action.ts index 6310024..d29d6ce 100644 --- a/src/client/actions/Action.ts +++ b/src/client/actions/Action.ts @@ -1,6 +1,6 @@ -import type { Client } from '../Client' +import type { Client } from '../Client.ts'; export abstract class Action { - constructor(public client: Client) {} - abstract handle(data: unknown): unknown + constructor(public client: Client) {} + abstract handle(data: unknown): unknown; } diff --git a/src/client/actions/ActionManager.ts b/src/client/actions/ActionManager.ts index 460ab34..5bab55f 100644 --- a/src/client/actions/ActionManager.ts +++ b/src/client/actions/ActionManager.ts @@ -1,19 +1,19 @@ -import * as Actions from './index' -import { Action as BaseAction } from './Action' -import { Client } from '../Client' +import * as Actions from './mod.ts'; +import { Action as BaseAction } from './Action.ts'; +import { Client } from '../Client.ts'; export class ActionManager { - private actions: Record = {} + private actions: Record = {}; - constructor(public client: Client) { - for (const Action of Object.values(Actions)) this.register(Action) - } + constructor(public client: Client) { + for (const Action of Object.values(Actions)) this.register(Action); + } - register(Action: new (client: Client) => BaseAction): void { - this.actions[Action.name.replace(/Action$/, '')] = new Action(this.client) - } + register(Action: new (client: Client) => BaseAction): void { + this.actions[Action.name.replace(/Action$/, '')] = new Action(this.client); + } - get(name: string): BaseAction | null { - return this.actions[name as keyof ActionManager] ?? null - } + get(name: string): BaseAction | null { + return this.actions[name as keyof ActionManager] ?? null; + } } diff --git a/src/client/actions/ChannelCreate.ts b/src/client/actions/ChannelCreate.ts index 3297a58..7a0b989 100644 --- a/src/client/actions/ChannelCreate.ts +++ b/src/client/actions/ChannelCreate.ts @@ -1,19 +1,20 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ChannelCreateAction extends Action { - async handle(data: APIChannel): Promise { - const channel = this.client.channels._add(data) + async handle(data: APIChannel): Promise { + const channel = this.client.channels._add(data); - if (channel) { - if (channel.inServer()) { - const server = channel.server ?? (await this.client.servers.fetch(channel.serverId)) - server.channels.cache.set(channel.id, channel) - } - this.client.emit(Events.CHANNEL_CREATE, channel) - } - - return { channel } + if (channel) { + if (channel.inServer()) { + const server = channel.server ?? + (await this.client.servers.fetch(channel.serverId)); + server.channels.cache.set(channel.id, channel); + } + this.client.emit(Events.CHANNEL_CREATE, channel); } + + return { channel }; + } } diff --git a/src/client/actions/ChannelDelete.ts b/src/client/actions/ChannelDelete.ts index c2f530e..625a63a 100644 --- a/src/client/actions/ChannelDelete.ts +++ b/src/client/actions/ChannelDelete.ts @@ -1,17 +1,17 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ChannelDeleteAction extends Action { - handle(data: { id: string }): unknown { - const channel = this.client.channels.cache.get(data.id) + handle(data: { id: string }): unknown { + const channel = this.client.channels.cache.get(data.id); - if (channel) { - if (channel.inServer()) { - channel.server?.channels.cache.delete(channel.id) - } - this.client.emit(Events.CHANNEL_DELETE, channel) - } - - return { channel } + if (channel) { + if (channel.inServer()) { + channel.server?.channels.cache.delete(channel.id); + } + this.client.emit(Events.CHANNEL_DELETE, channel); } + + return { channel }; + } } diff --git a/src/client/actions/ChannelGroupJoin.ts b/src/client/actions/ChannelGroupJoin.ts index e67a70f..1cd0ffa 100644 --- a/src/client/actions/ChannelGroupJoin.ts +++ b/src/client/actions/ChannelGroupJoin.ts @@ -1,16 +1,16 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ChannelGroupJoinAction extends Action { - async handle(data: { id: string; user: string }): Promise { - const channel = this.client.channels.cache.get(data.id) - const user = await this.client.users.fetch(data.user, { force: false }) + async handle(data: { id: string; user: string }): Promise { + const channel = this.client.channels.cache.get(data.id); + const user = await this.client.users.fetch(data.user, { force: false }); - if (channel?.isGroup()) { - channel.users.set(user.id, user) - this.client.emit(Events.GROUP_JOIN, channel, user) - } - - return { channel, user } + if (channel?.isGroup()) { + channel.users.set(user.id, user); + this.client.emit(Events.GROUP_JOIN, channel, user); } + + return { channel, user }; + } } diff --git a/src/client/actions/ChannelGroupLeave.ts b/src/client/actions/ChannelGroupLeave.ts index 95f27fe..6872e5c 100644 --- a/src/client/actions/ChannelGroupLeave.ts +++ b/src/client/actions/ChannelGroupLeave.ts @@ -1,16 +1,16 @@ -import { Action } from './Action' -import { Events } from '../../util/index' +import { Action } from './Action.ts'; +import { Events } from '../../util/mod.ts'; export class ChannelGroupLeaveAction extends Action { - async handle(data: { id: string; user: string }): Promise { - const channel = this.client.channels.cache.get(data.id) - const user = await this.client.users.fetch(data.user, { force: false }) + async handle(data: { id: string; user: string }): Promise { + const channel = this.client.channels.cache.get(data.id); + const user = await this.client.users.fetch(data.user, { force: false }); - if (channel?.isGroup()) { - channel.users.delete(data.user) - this.client.emit(Events.GROUP_LEAVE, channel, user) - } - - return { channel, user } + if (channel?.isGroup()) { + channel.users.delete(data.user); + this.client.emit(Events.GROUP_LEAVE, channel, user); } + + return { channel, user }; + } } diff --git a/src/client/actions/ChannelStartTyping.ts b/src/client/actions/ChannelStartTyping.ts index 325da9d..b1a32fa 100644 --- a/src/client/actions/ChannelStartTyping.ts +++ b/src/client/actions/ChannelStartTyping.ts @@ -1,15 +1,15 @@ -import { Action } from './Action' -import { Events } from '../../util/index' +import { Action } from './Action.ts'; +import { Events } from '../../util/mod.ts'; export class ChannelStartTypingAction extends Action { - handle(data: { id: string; user: string }): unknown { - const channel = this.client.channels.cache.get(data.id) - const user = this.client.users.cache.get(data.user) + handle(data: { id: string; user: string }): unknown { + const channel = this.client.channels.cache.get(data.id); + const user = this.client.users.cache.get(data.user); - if (channel?.isText() && user) { - this.client.emit(Events.TYPING_START, channel, user) - } - - return { channel, user } + if (channel?.isText() && user) { + this.client.emit(Events.TYPING_START, channel, user); } + + return { channel, user }; + } } diff --git a/src/client/actions/ChannelStopTyping.ts b/src/client/actions/ChannelStopTyping.ts index 75b3eda..d44f99b 100644 --- a/src/client/actions/ChannelStopTyping.ts +++ b/src/client/actions/ChannelStopTyping.ts @@ -1,15 +1,15 @@ -import { Action } from './Action' -import { Events } from '../../util/index' +import { Action } from './Action.ts'; +import { Events } from '../../util/mod.ts'; export class ChannelStopTypingAction extends Action { - handle(data: { id: string; user: string }): unknown { - const channel = this.client.channels.cache.get(data.id) - const user = this.client.users.cache.get(data.user) + handle(data: { id: string; user: string }): unknown { + const channel = this.client.channels.cache.get(data.id); + const user = this.client.users.cache.get(data.user); - if (channel?.isText() && user) { - this.client.emit(Events.TYPING_STOP, channel, user) - } - - return { channel, user } + if (channel?.isText() && user) { + this.client.emit(Events.TYPING_STOP, channel, user); } + + return { channel, user }; + } } diff --git a/src/client/actions/ChannelUpdate.ts b/src/client/actions/ChannelUpdate.ts index 71194d8..8b89473 100644 --- a/src/client/actions/ChannelUpdate.ts +++ b/src/client/actions/ChannelUpdate.ts @@ -1,20 +1,20 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ChannelUpdateAction extends Action { - handle(data: { id: string; data: APIChannel }): unknown { - const oldChannel = this.client.channels.cache.get(data.id) + handle(data: { id: string; data: APIChannel }): unknown { + const oldChannel = this.client.channels.cache.get(data.id); - if (oldChannel) { - const newChannel = oldChannel._update(data.data) + if (oldChannel) { + const newChannel = oldChannel._update(data.data); - this.client.channels.cache.set(newChannel.id, newChannel) - this.client.emit(Events.CHANNEL_UPDATE, oldChannel, newChannel) + this.client.channels.cache.set(newChannel.id, newChannel); + this.client.emit(Events.CHANNEL_UPDATE, oldChannel, newChannel); - return { newChannel, oldChannel } - } - - return { oldChannel } + return { newChannel, oldChannel }; } + + return { oldChannel }; + } } diff --git a/src/client/actions/Message.ts b/src/client/actions/Message.ts index b5e03b8..ee1499f 100644 --- a/src/client/actions/Message.ts +++ b/src/client/actions/Message.ts @@ -1,21 +1,23 @@ -import type { Message as APIMessage } from 'revolt-api' -import { Action } from './Action' -import { Events, SYSTEM_USER_ID } from '../../util/Constants' +import type { Message as APIMessage } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events, SYSTEM_USER_ID } from '../../util/Constants.ts'; export class MessageAction extends Action { - async handle(data: APIMessage): Promise { - const channel = this.client.channels.cache.get(data.channel) + async handle(data: APIMessage): Promise { + const channel = this.client.channels.cache.get(data.channel); - if (channel?.isText()) { - const message = channel.messages._add(data) + if (channel?.isText()) { + const message = channel.messages._add(data); - if (data.author !== SYSTEM_USER_ID) await this.client.users.fetch(data.author, { force: false }) + if (data.author !== SYSTEM_USER_ID) { + await this.client.users.fetch(data.author, { force: false }); + } - this.client.emit(Events.MESSAGE, message) + this.client.emit(Events.MESSAGE, message); - return { message } - } - - return {} + return { message }; } + + return {}; + } } diff --git a/src/client/actions/MessageDelete.ts b/src/client/actions/MessageDelete.ts index bf82cf3..7159cf1 100644 --- a/src/client/actions/MessageDelete.ts +++ b/src/client/actions/MessageDelete.ts @@ -1,21 +1,21 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class MessageDeleteAction extends Action { - handle(data: { id: string; channel: string }): unknown { - const channel = this.client.channels.cache.get(data.channel) + handle(data: { id: string; channel: string }): unknown { + const channel = this.client.channels.cache.get(data.channel); - if (channel?.isText()) { - const message = channel.messages.cache.get(data.id) + if (channel?.isText()) { + const message = channel.messages.cache.get(data.id); - if (message) { - channel.messages._remove(message.id) - this.client.emit(Events.MESSAGE_DELETE, message) - } + if (message) { + channel.messages._remove(message.id); + this.client.emit(Events.MESSAGE_DELETE, message); + } - return { message } - } - - return {} + return { message }; } + + return {}; + } } diff --git a/src/client/actions/MessageUpdate.ts b/src/client/actions/MessageUpdate.ts index a74b02c..e387f1e 100644 --- a/src/client/actions/MessageUpdate.ts +++ b/src/client/actions/MessageUpdate.ts @@ -1,25 +1,25 @@ -import type { Message as APIMessage } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Message as APIMessage } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class MessageUpdateAction extends Action { - handle(data: { id: string; channel: string; data: APIMessage }): unknown { - const channel = this.client.channels.cache.get(data.channel) + handle(data: { id: string; channel: string; data: APIMessage }): unknown { + const channel = this.client.channels.cache.get(data.channel); - if (!channel?.isText()) return + if (!channel?.isText()) return; - const oldMessage = channel?.messages.cache.get(data.id) + const oldMessage = channel?.messages.cache.get(data.id); - if (oldMessage) { - const newMessage = oldMessage._update(data.data) + if (oldMessage) { + const newMessage = oldMessage._update(data.data); - channel.messages.cache.set(newMessage.id, newMessage) + channel.messages.cache.set(newMessage.id, newMessage); - this.client.emit(Events.MESSAGE_UPDATE, oldMessage, newMessage) + this.client.emit(Events.MESSAGE_UPDATE, oldMessage, newMessage); - return { newMessage, oldMessage } - } - - return { oldMessage } + return { newMessage, oldMessage }; } + + return { oldMessage }; + } } diff --git a/src/client/actions/ServerDelete.ts b/src/client/actions/ServerDelete.ts index faf6d78..382dff9 100644 --- a/src/client/actions/ServerDelete.ts +++ b/src/client/actions/ServerDelete.ts @@ -1,16 +1,16 @@ -import type { Server as APIServer } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerDeleteAction extends Action { - handle(data: APIServer): unknown { - const server = this.client.servers.cache.get(data._id) + handle(data: APIServer): unknown { + const server = this.client.servers.cache.get(data._id); - if (server) { - this.client.servers._remove(server.id) - this.client.emit(Events.SERVER_DELETE, server) - } - - return { server } + if (server) { + this.client.servers._remove(server.id); + this.client.emit(Events.SERVER_DELETE, server); } + + return { server }; + } } diff --git a/src/client/actions/ServerMemberJoin.ts b/src/client/actions/ServerMemberJoin.ts index 8d68216..da6c09a 100644 --- a/src/client/actions/ServerMemberJoin.ts +++ b/src/client/actions/ServerMemberJoin.ts @@ -1,21 +1,21 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerMemberJoin extends Action { - async handle(data: { id: string; user: string }): Promise { - let server = this.client.servers.cache.get(data.id) + async handle(data: { id: string; user: string }): Promise { + let server = this.client.servers.cache.get(data.id); - if (!server) { - server = await this.client.servers.fetch(data.id) - this.client.emit(Events.SERVER_CREATE, server) - } + if (!server) { + server = await this.client.servers.fetch(data.id); + this.client.emit(Events.SERVER_CREATE, server); + } - const member = await server.members.fetch(data.user) + const member = await server.members.fetch(data.user); - server.members.cache.set(member.id, member) + server.members.cache.set(member.id, member); - this.client.emit(Events.SERVER_MEMBER_JOIN, member) + this.client.emit(Events.SERVER_MEMBER_JOIN, member); - return { member } - } + return { member }; + } } diff --git a/src/client/actions/ServerMemberLeave.ts b/src/client/actions/ServerMemberLeave.ts index f9db117..08a192b 100644 --- a/src/client/actions/ServerMemberLeave.ts +++ b/src/client/actions/ServerMemberLeave.ts @@ -1,21 +1,21 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerMemberLeaveAction extends Action { - handle(data: { id: string; user: string }): unknown { - const server = this.client.servers.cache.get(data.id) + handle(data: { id: string; user: string }): unknown { + const server = this.client.servers.cache.get(data.id); - if (server) { - const member = server.members.cache.get(data.user) + if (server) { + const member = server.members.cache.get(data.user); - if (member) { - server.members._remove(member.id) - this.client.emit(Events.SERVER_MEMBER_LEAVE, member) - } + if (member) { + server.members._remove(member.id); + this.client.emit(Events.SERVER_MEMBER_LEAVE, member); + } - return { server, member } - } - - return { server } + return { server, member }; } + + return { server }; + } } diff --git a/src/client/actions/ServerMemberUpdate.ts b/src/client/actions/ServerMemberUpdate.ts index 5a3e61e..acbf30c 100644 --- a/src/client/actions/ServerMemberUpdate.ts +++ b/src/client/actions/ServerMemberUpdate.ts @@ -1,22 +1,22 @@ -import type { Member as APIMember } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Member as APIMember } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerMemberUpdateAction extends Action { - handle(data: { id: string; data: APIMember }): unknown { - const server = this.client.servers.cache.get(data.id) - const oldMember = server?.members.cache.get(data.data?._id?.user) + handle(data: { id: string; data: APIMember }): unknown { + const server = this.client.servers.cache.get(data.id); + const oldMember = server?.members.cache.get(data.data?._id?.user); - if (server && oldMember) { - const newMember = oldMember._update(data.data) + if (server && oldMember) { + const newMember = oldMember._update(data.data); - server.members.cache.set(newMember.id, newMember) + server.members.cache.set(newMember.id, newMember); - this.client.emit(Events.SERVER_MEMBER_UPDATE, oldMember, newMember) + this.client.emit(Events.SERVER_MEMBER_UPDATE, oldMember, newMember); - return { newMember, oldMember } - } - - return { oldMember } + return { newMember, oldMember }; } + + return { oldMember }; + } } diff --git a/src/client/actions/ServerRoleDelete.ts b/src/client/actions/ServerRoleDelete.ts index a3edc5a..dd61d2f 100644 --- a/src/client/actions/ServerRoleDelete.ts +++ b/src/client/actions/ServerRoleDelete.ts @@ -1,21 +1,21 @@ -import { Action } from './Action' -import { Events } from '../../util/Constants' +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerRoleDeleteAction extends Action { - handle(data: { id: string; role_id: string }): unknown { - const server = this.client.servers.cache.get(data.id) + handle(data: { id: string; role_id: string }): unknown { + const server = this.client.servers.cache.get(data.id); - if (server) { - const role = server.roles.cache.get(data.role_id) + if (server) { + const role = server.roles.cache.get(data.role_id); - if (role) { - server.roles._remove(role.id) - this.client.emit(Events.ROLE_DELETE, role) - } + if (role) { + server.roles._remove(role.id); + this.client.emit(Events.ROLE_DELETE, role); + } - return { role } - } - - return {} + return { role }; } + + return {}; + } } diff --git a/src/client/actions/ServerUpdate.ts b/src/client/actions/ServerUpdate.ts index 874bbeb..1b0415a 100644 --- a/src/client/actions/ServerUpdate.ts +++ b/src/client/actions/ServerUpdate.ts @@ -1,21 +1,21 @@ -import type { Server as APIServer } from 'revolt-api' -import { Action } from './Action' -import { Events } from '../../util/Constants' +import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { Events } from '../../util/Constants.ts'; export class ServerUpdateAction extends Action { - handle(data: { id: string; data: APIServer }): unknown { - const oldServer = this.client.servers.cache.get(data.id) + handle(data: { id: string; data: APIServer }): unknown { + const oldServer = this.client.servers.cache.get(data.id); - if (oldServer) { - const newServer = oldServer._update(data.data) + if (oldServer) { + const newServer = oldServer._update(data.data); - this.client.servers.cache.set(newServer.id, newServer) + this.client.servers.cache.set(newServer.id, newServer); - this.client.emit(Events.SERVER_UPDATE, oldServer, newServer) + this.client.emit(Events.SERVER_UPDATE, oldServer, newServer); - return { newServer, oldServer } - } - - return { oldServer } + return { newServer, oldServer }; } + + return { oldServer }; + } } diff --git a/src/client/actions/UserUpdate.ts b/src/client/actions/UserUpdate.ts index f2680ad..bb10283 100644 --- a/src/client/actions/UserUpdate.ts +++ b/src/client/actions/UserUpdate.ts @@ -1,26 +1,26 @@ -import type { User as APIUser } from 'revolt-api' -import { Action } from './Action' -import { ClientUser } from '../../structures/ClientUser' -import { Events } from '../../util/Constants' +import type { User as APIUser } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Action } from './Action.ts'; +import { ClientUser } from '../../structures/ClientUser.ts'; +import { Events } from '../../util/Constants.ts'; export class UserUpdateAction extends Action { - handle(data: { id: string; data: APIUser }): unknown { - const oldUser = this.client.users.cache.get(data.id) + handle(data: { id: string; data: APIUser }): unknown { + const oldUser = this.client.users.cache.get(data.id); - if (oldUser) { - const newUser = oldUser._update(data.data) + if (oldUser) { + const newUser = oldUser._update(data.data); - this.client.users.cache.set(newUser.id, newUser) + this.client.users.cache.set(newUser.id, newUser); - if (data.id === this.client.user?.id) { - this.client.user = new ClientUser(this.client, data.data) - } + if (data.id === this.client.user?.id) { + this.client.user = new ClientUser(this.client, data.data); + } - this.client.emit(Events.USER_UPDATE, oldUser, newUser) + this.client.emit(Events.USER_UPDATE, oldUser, newUser); - return { newUser, oldUser } - } - - return { oldUser } + return { newUser, oldUser }; } + + return { oldUser }; + } } diff --git a/src/client/actions/index.ts b/src/client/actions/index.ts deleted file mode 100644 index 541220a..0000000 --- a/src/client/actions/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './ChannelCreate' -export * from './ChannelDelete' -export * from './ChannelGroupJoin' -export * from './ChannelGroupLeave' -export * from './ChannelStartTyping' -export * from './ChannelStopTyping' -export * from './Message' -export * from './MessageDelete' -export * from './MessageUpdate' -export * from './ServerDelete' -export * from './ServerMemberJoin' -export * from './ServerMemberLeave' -export * from './ServerMemberUpdate' -export * from './ServerRoleDelete' -export * from './ServerUpdate' -export * from './UserUpdate' diff --git a/src/client/actions/mod.ts b/src/client/actions/mod.ts new file mode 100644 index 0000000..f11e75e --- /dev/null +++ b/src/client/actions/mod.ts @@ -0,0 +1,16 @@ +export * from './ChannelCreate.ts'; +export * from './ChannelDelete.ts'; +export * from './ChannelGroupJoin.ts'; +export * from './ChannelGroupLeave.ts'; +export * from './ChannelStartTyping.ts'; +export * from './ChannelStopTyping.ts'; +export * from './Message.ts'; +export * from './MessageDelete.ts'; +export * from './MessageUpdate.ts'; +export * from './ServerDelete.ts'; +export * from './ServerMemberJoin.ts'; +export * from './ServerMemberLeave.ts'; +export * from './ServerMemberUpdate.ts'; +export * from './ServerRoleDelete.ts'; +export * from './ServerUpdate.ts'; +export * from './UserUpdate.ts'; diff --git a/src/client/index.ts b/src/client/index.ts deleted file mode 100644 index a3db8c4..0000000 --- a/src/client/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './BaseClient' -export * from './WebSocket' -export * from './Client' diff --git a/src/client/mod.ts b/src/client/mod.ts new file mode 100644 index 0000000..ecccb39 --- /dev/null +++ b/src/client/mod.ts @@ -0,0 +1,3 @@ +export * from './BaseClient.ts'; +export * from './WebSocket.ts'; +export * from './Client.ts'; diff --git a/src/errors/Messages.ts b/src/errors/Messages.ts index ab07878..1c4b825 100644 --- a/src/errors/Messages.ts +++ b/src/errors/Messages.ts @@ -1,5 +1,9 @@ export const Messages = { - INVALID_TYPE: (name: string, expected: string, an = false): string => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, - BITFIELD_INVALID: (bit: unknown): string => `Invalid bitfield flag or number: ${bit}.`, - INVALID_TOKEN: () => 'Invalid token received' -} + INVALID_TYPE: (name: string, expected: string, an = false): string => + `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, + BITFIELD_INVALID: (bit: unknown): string => + `Invalid bitfield flag or number: ${bit}.`, + INVALID_TOKEN: () => 'Invalid token received', + MISSING_CONFIGURATION_SYNC: () => + 'Attempted to open WebSocket without syncing configuration from server.', +}; diff --git a/src/errors/index.ts b/src/errors/index.ts deleted file mode 100644 index d3fa292..0000000 --- a/src/errors/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Messages } from './Messages' - -const createCustomError = (Base: ErrorConstructor) => { - return class RevoltError extends Base { - constructor(key: K, ...args: Parameters) { - const msg = Messages[key] as (...args: unknown[]) => string - super(msg(...args)) - Base.captureStackTrace(this, RevoltError) - } - } -} - -export const Error = createCustomError(globalThis.Error) -export const TypeError = createCustomError(globalThis.TypeError) -export const RangeError = createCustomError(globalThis.RangeError) diff --git a/src/errors/mod.ts b/src/errors/mod.ts new file mode 100644 index 0000000..4556c59 --- /dev/null +++ b/src/errors/mod.ts @@ -0,0 +1,17 @@ +import { Messages } from './Messages.ts'; + +const createCustomError = (Base: ErrorConstructor) => { + return class RevoltError< + K extends keyof typeof Messages = keyof typeof Messages, + > extends Base { + constructor(key: K, ...args: Parameters) { + const msg = Messages[key] as (...args: unknown[]) => string; + super(msg(...args)); + Base.captureStackTrace(this, RevoltError); + } + }; +}; + +export const Error = createCustomError(globalThis.Error); +export const TypeError = createCustomError(globalThis.TypeError); +export const RangeError = createCustomError(globalThis.RangeError); diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index feb1ab5..0000000 --- a/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { Client } from './client/Client' -export * from './managers/index' -export * from './structures/index' -export * from './util/index' diff --git a/src/lib.ts b/src/lib.ts new file mode 100644 index 0000000..b7df9c0 --- /dev/null +++ b/src/lib.ts @@ -0,0 +1,4 @@ +export { Client } from './client/Client.ts'; +export * from './managers/mod.ts'; +export * from './structures/mod.ts'; +export * from './util/mod.ts'; diff --git a/src/managers/BaseManager.ts b/src/managers/BaseManager.ts index e6b42df..e14a0b0 100644 --- a/src/managers/BaseManager.ts +++ b/src/managers/BaseManager.ts @@ -1,47 +1,49 @@ -import type { Client } from '../client/Client' -import { Collection } from '../util/index' +import type { Client } from '../client/Client.ts'; +import { Collection } from '../util/mod.ts'; export abstract class BaseManager { - readonly cache = new Collection() - - constructor(protected readonly client: Client) {} - - _add(raw: R): Holds { - if (!this.holds) throw new Error('No "holds" exists.') - const obj = new this.holds(this.client, raw) - this.cache.set(obj.id, obj) - return obj - } - - _remove(id: string): void { - this.cache.delete(id) - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - abstract readonly holds: (new (...args: any[]) => Holds) | null - - resolve(resolvable: Holds): Holds | null - resolve(resolvable: string | R): Holds | null - resolve(resolvable: string | R | Holds): Holds | null - resolve(resolvable: string | R | Holds): Holds | null { - if (resolvable == null) return null - if (typeof resolvable === 'string') return this.cache.get(resolvable) ?? null - if (this.holds && resolvable instanceof this.holds) return resolvable - const raw = resolvable as unknown as { _id: string } - if ('_id' in raw) return this.cache.get(raw._id) ?? null - return null - } - - resolveId(resolvable: string | Holds | R): string | null { - if (resolvable == null) return null - if (typeof resolvable === 'string') return resolvable - if (this.holds && resolvable instanceof this.holds) return resolvable.id - const raw = resolvable as unknown as { _id: string } - if ('_id' in raw) raw._id ?? null - return null - } - - valueOf(): this['cache'] { - return this.cache + readonly cache = new Collection(); + + constructor(protected readonly client: Client) {} + + _add(raw: R): Holds { + if (!this.holds) throw new Error('No "holds" exists.'); + const obj = new this.holds(this.client, raw); + this.cache.set(obj.id, obj); + return obj; + } + + _remove(id: string): void { + this.cache.delete(id); + } + + // deno-lint-ignore no-explicit-any + abstract readonly holds: (new (...args: any[]) => Holds) | null; + + resolve(resolvable: Holds): Holds | null; + resolve(resolvable: string | R): Holds | null; + resolve(resolvable: string | R | Holds): Holds | null; + resolve(resolvable: string | R | Holds): Holds | null { + if (resolvable == null) return null; + if (typeof resolvable === 'string') { + return this.cache.get(resolvable) ?? null; } + if (this.holds && resolvable instanceof this.holds) return resolvable; + const raw = resolvable as unknown as { _id: string }; + if ('_id' in raw) return this.cache.get(raw._id) ?? null; + return null; + } + + resolveId(resolvable: string | Holds | R): string | null { + if (resolvable == null) return null; + if (typeof resolvable === 'string') return resolvable; + if (this.holds && resolvable instanceof this.holds) return resolvable.id; + const raw = resolvable as unknown as { _id: string }; + if ('_id' in raw) raw._id ?? null; + return null; + } + + valueOf(): this['cache'] { + return this.cache; + } } diff --git a/src/managers/ChannelManager.ts b/src/managers/ChannelManager.ts index 0e4047d..56d249b 100644 --- a/src/managers/ChannelManager.ts +++ b/src/managers/ChannelManager.ts @@ -1,64 +1,94 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Channel, NotesChannel } from '../structures/index' -import { ChannelTypes } from '../util/index' - -export type ChannelResolvable = Channel | APIChannel | string +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { + Channel, + DMChannel, + GroupChannel, + NotesChannel, + TextChannel, + VoiceChannel, +} from '../structures/mod.ts'; + +export type ChannelResolvable = Channel | APIChannel | string; export class ChannelManager extends BaseManager { - holds = null + holds = null; + + _add(data: APIChannel): Channel { + let channel: Channel; + + switch (data.channel_type) { + case 'TextChannel': + channel = new TextChannel(this.client, data); + break; + case 'VoiceChannel': + channel = new VoiceChannel(this.client, data); + break; + case 'DirectMessage': + channel = new DMChannel(this.client, data); + break; + case 'Group': + channel = new GroupChannel(this.client, data); + break; + case 'SavedMessages': + channel = new NotesChannel(this.client, data); + if (this.client.user) this.client.user.notes = channel as NotesChannel; + break; + default: + throw new Error(`Unknown Channel Type: ${data}`); + } - _add(raw: APIChannel): Channel { - const channel = Channel.create(this.client, raw) + this.cache.set(channel.id, channel); - if (channel.type === ChannelTypes.NOTES && this.client.user) { - this.client.user.notes = channel as NotesChannel - } + return channel; + } - this.cache.set(channel.id, channel) + _remove(id: string): void { + const channel = this.cache.get(id); - return channel + if (channel?.inServer()) { + channel.server?.channels.cache.delete(id); } - _remove(id: string): void { - const channel = this.cache.get(id) - - if (channel?.inServer()) { - channel.server?.channels.cache.delete(id) - } - - super._remove(id) - } + super._remove(id); + } - async delete(channel: ChannelResolvable): Promise { - const id = this.resolveId(channel) - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable') - await this.client.api.delete(`/channels/${id}`) + async delete(channel: ChannelResolvable): Promise { + const id = this.resolveId(channel); + if (!id) { + throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable'); } + await this.client.api.delete(`/channels/${id}`); + } - async fetch(channel: ChannelResolvable, { force = true } = {}): Promise { - const id = this.resolveId(channel) + async fetch( + channel: ChannelResolvable, + { force = true } = {}, + ): Promise { + const id = this.resolveId(channel); - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable') + if (!id) { + throw new TypeError('INVALID_TYPE', 'channel', 'ChannelResolvable'); + } - if (!force) { - const channel = this.cache.get(id) - if (channel) return channel - } + if (!force) { + const channel = this.cache.get(id); + if (channel) return channel; + } - const data = (await this.client.api.get(`/channels/${id}`)) as APIChannel + const data = await this.client.api.get(`/channels/${id}`); - return this._add(data) - } + return this._add(data); + } - resolve(channel: ChannelResolvable): Channel | null { - if (channel instanceof Channel) return channel - return super.resolve(channel) - } + resolve(channel: ChannelResolvable): Channel | null { + if (channel instanceof Channel) return channel; + return super.resolve(channel); + } - resolveId(channel: ChannelResolvable): string | null { - if (channel instanceof Channel) return channel.id - return super.resolveId(channel) - } + resolveId(channel: ChannelResolvable): string | null { + if (channel instanceof Channel) return channel.id; + return super.resolveId(channel); + } } diff --git a/src/managers/MessageManager.ts b/src/managers/MessageManager.ts index 1b518b1..eff85e1 100644 --- a/src/managers/MessageManager.ts +++ b/src/managers/MessageManager.ts @@ -1,154 +1,188 @@ -import type { User as APIUser, Message as APIMessage, Member as APIMember } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Channel, Message, ServerMember, User } from '../structures/index' -import { Collection, UUID } from '../util/index' - -export type MessageResolvable = Message | APIMessage | string +import type { + Member as APIMember, + Message as APIMessage, + User as APIUser, +} from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Channel, Message, ServerMember, User } from '../structures/mod.ts'; +import { Collection, UUID } from '../util/mod.ts'; + +export type MessageResolvable = Message | APIMessage | string; export interface EditMessageOptions { - content?: string + content?: string; } export interface MessageOptions { - content: string - replies?: unknown[] - attachments?: string[] + content: string; + replies?: unknown[]; + attachments?: string[]; } export interface SearchMessageQuery { - query: string - limit?: number - before?: string - after?: string - sort?: 'Relevance' | 'Latest' | 'Oldest' - include_users?: boolean + query: string; + limit?: number; + before?: string; + after?: string; + sort?: 'Relevance' | 'Latest' | 'Oldest'; + include_users?: boolean; } type SearchResultWithUsers = { - users: Collection - messages: Collection - members: Collection -} + users: Collection; + messages: Collection; + members: Collection; +}; export class MessageManager extends BaseManager { - holds = Message - constructor(protected readonly channel: Channel) { - super(channel.client) - } - - private async _fetchId(messageId: string) { - const data = await this.client.api.get(`/channels/${this.channel.id}/messages/${messageId}`) - return this._add(data) - } - - private async _fetchMany(withUsers = true) { - const { messages } = await this.client.api.get(`/channels/${this.channel.id}/messages?include_users=${withUsers}`) - return (messages as APIMessage[]).reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) + holds = Message; + constructor(protected readonly channel: Channel) { + super(channel.client); + } + + private async _fetchId(messageId: string) { + const data = await this.client.api.get( + `/channels/${this.channel.id}/messages/${messageId}`, + ) as APIMessage; + return this._add(data); + } + + private async _fetchMany(withUsers = true) { + const { messages } = await this.client.api.get( + `/channels/${this.channel.id}/messages?include_users=${withUsers}`, + ); + return (messages as APIMessage[]).reduce((coll, cur) => { + const msg = this._add(cur); + coll.set(msg.id, msg); + return coll; + }, new Collection()); + } + + async send(options: MessageOptions | string): Promise { + const { content, replies, attachments }: MessageOptions = + typeof options === 'object' ? { ...options } : { content: options }; + + const data = await this.client.api.post( + `/channels/${this.channel.id}/messages`, + { + body: { + content, + nonce: UUID.generate(), + replies, + attachments, + }, + }, + ) as APIMessage; + + return this._add(data); + } + + async ack(message: MessageResolvable): Promise { + const id = this.resolveId(message); + if (!id) { + throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); } + await this.client.api.put(`/channels/${this.channel.id}/ack/${id}`); + } - async send(_options: MessageOptions | string): Promise { - const { content, replies, attachments }: MessageOptions = - typeof _options === 'object' - ? { ..._options } - : { - content: _options - } - - const data = await this.client.api.post(`/channels/${this.channel.id}/messages`, { - body: { - content, - nonce: UUID.generate(), - replies, - attachments - } - }) - - return this._add(data) + async delete(message: MessageResolvable): Promise { + const id = this.resolveId(message); + if (!id) { + throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); } - - async ack(message: MessageResolvable): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.put(`/channels/${this.channel.id}/ack/${id}`) - } - - async delete(message: MessageResolvable): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.delete(`/channels/${this.channel.id}/messages/${id}`) + await this.client.api.delete(`/channels/${this.channel.id}/messages/${id}`); + } + + async edit( + message: MessageResolvable, + options: EditMessageOptions, + ): Promise { + const id = this.resolveId(message); + if (!id) { + throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); } - - async edit(message: MessageResolvable, options: EditMessageOptions): Promise { - const id = this.resolveId(message) - if (!id) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable') - await this.client.api.patch(`/channels/${this.channel.id}/messages/${id}`, { body: options }) - } - - async search(query: SearchMessageQuery & { include_users: true }): Promise - async search(query: SearchMessageQuery): Promise> - async search(query: SearchMessageQuery): Promise | SearchResultWithUsers> { - if (query.include_users) { - const response = (await this.client.api.post(`/channels/${this.channel.id}/search`, { body: query })) as { - users: APIUser[] - messages: APIMessage[] - members: APIMember[] - } - - const users = response.users.reduce((coll, cur) => { - const user = this.client.users._add(cur) - coll.set(user.id, user) - return coll - }, new Collection()) - - const messages = response.messages.reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) - - const server = this.client.servers.cache.get(response.members[0]?._id.server) - - if (server) { - const members = response.members.reduce((coll, cur) => { - const member = server!.members._add(cur) - coll.set(cur._id.user, member) - return coll - }, new Collection()) - - return { messages, users, members } - } - - return { messages, users, members: new Collection() } - } - - const response = (await this.client.api.post(`/channels/${this.channel.id}/search`, { body: query })) as APIMessage[] - - return response.reduce((coll, cur) => { - const msg = this._add(cur) - coll.set(msg.id, msg) - return coll - }, new Collection()) + await this.client.api.patch(`/channels/${this.channel.id}/messages/${id}`, { + body: options, + }); + } + + async search( + query: SearchMessageQuery & { include_users: true }, + ): Promise; + async search(query: SearchMessageQuery): Promise>; + async search( + query: SearchMessageQuery, + ): Promise | SearchResultWithUsers> { + if (query.include_users) { + const response = + (await this.client.api.post(`/channels/${this.channel.id}/search`, { + body: query, + })) as { + users: APIUser[]; + messages: APIMessage[]; + members: APIMember[]; + }; + + const users = response.users.reduce((coll, cur) => { + const user = this.client.users._add(cur); + coll.set(user.id, user); + return coll; + }, new Collection()); + + const messages = response.messages.reduce((coll, cur) => { + const msg = this._add(cur); + coll.set(msg.id, msg); + return coll; + }, new Collection()); + + const server = this.client.servers.cache.get( + response.members[0]?._id.server, + ); + + if (server) { + const members = response.members.reduce((coll, cur) => { + const member = server!.members._add(cur); + coll.set(cur._id.user, member); + return coll; + }, new Collection()); + + return { messages, users, members }; + } + + return { messages, users, members: new Collection() }; } - fetch(messageId: string): Promise - fetch(options: { includeUsers: true }): Promise<{ - users: Collection - messages: Collection - }> - fetch(options?: { includeUsers?: false }): Promise> - fetch(options?: string | { includeUsers?: boolean }): Promise< - | Collection - | { - users: Collection - messages: Collection - } - | Message - > { - return typeof options === 'string' ? this._fetchId(options) : this._fetchMany(options?.['includeUsers']) + const response = + (await this.client.api.post(`/channels/${this.channel.id}/search`, { + body: query, + })) as APIMessage[]; + + return response.reduce((coll, cur) => { + const msg = this._add(cur); + coll.set(msg.id, msg); + return coll; + }, new Collection()); + } + + fetch(messageId: string): Promise; + fetch(options: { includeUsers: true }): Promise<{ + users: Collection; + messages: Collection; + }>; + fetch( + options?: { includeUsers?: false }, + ): Promise>; + fetch(options?: string | { includeUsers?: boolean }): Promise< + | Collection + | { + users: Collection; + messages: Collection; } + | Message + > { + return typeof options === 'string' + ? this._fetchId(options) + : this._fetchMany(options?.['includeUsers']); + } } diff --git a/src/managers/RoleManager.ts b/src/managers/RoleManager.ts index 4b1aada..ec464a9 100644 --- a/src/managers/RoleManager.ts +++ b/src/managers/RoleManager.ts @@ -1,30 +1,33 @@ -import type { Role as APIRole } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Role, Server } from '../structures/index' +import type { Role as APIRole } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Role, Server } from '../structures/mod.ts'; -export type RoleResolvable = Role | string +export type RoleResolvable = Role | string; export class RoleManager extends BaseManager { - holds = Role - constructor(protected readonly server: Server) { - super(server.client) - } + holds = Role; + constructor(protected readonly server: Server) { + super(server.client); + } - _add(data: APIRole & { id: string }): Role { - const role = new Role(this.server, data) - this.cache.set(role.id, role) - return role - } + _add(data: APIRole & { id: string }): Role { + const role = new Role(this.server, data); + this.cache.set(role.id, role); + return role; + } - async create(name: string): Promise { - const { id, role } = await this.client.api.post(`/servers/${this.server.id}/roles`, { body: { name } }) - return this._add(Object.assign(role, { id })) - } + async create(name: string): Promise { + const { id, role } = await this.client.api.post( + `/servers/${this.server.id}/roles`, + { body: { name } }, + ); + return this._add(Object.assign(role, { id })); + } - async delete(role: RoleResolvable): Promise { - const id = this.resolveId(role) - if (!id) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable') - await this.client.api.delete(`/servers/${this.server.id}/roles/${id}`) - } + async delete(role: RoleResolvable): Promise { + const id = this.resolveId(role); + if (!id) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable'); + await this.client.api.delete(`/servers/${this.server.id}/roles/${id}`); + } } diff --git a/src/managers/ServerChannelManager.ts b/src/managers/ServerChannelManager.ts index 778c0bd..fa89bf9 100644 --- a/src/managers/ServerChannelManager.ts +++ b/src/managers/ServerChannelManager.ts @@ -1,68 +1,88 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Server, ServerChannel, TextChannel, VoiceChannel } from '../structures/index' -import { UUID } from '../util/index' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { + Server, + ServerChannel, + TextChannel, + VoiceChannel, +} from '../structures/mod.ts'; +import { UUID } from '../util/mod.ts'; -type APIServerChannel = Extract +type APIServerChannel = Extract< + APIChannel, + { channel_type: 'TextChannel' | 'VoiceChannel' } +>; -export type ServerChannelResolvable = ServerChannel | APIServerChannel | string +export type ServerChannelResolvable = ServerChannel | APIServerChannel | string; export interface CreateChannelOptions { - name: string - type?: 'Text' | 'Voice' - description?: string + name: string; + type?: 'Text' | 'Voice'; + description?: string; } export class ServerChannelManager extends BaseManager { - holds = ServerChannel - constructor(protected readonly server: Server) { - super(server.client) - } - - _add(data: APIChannel): ServerChannel { - let channel: ServerChannel + holds = ServerChannel; + constructor(protected readonly server: Server) { + super(server.client); + } - switch (data.channel_type) { - case 'TextChannel': - channel = new TextChannel(this.client, data) - break - case 'VoiceChannel': - channel = new VoiceChannel(this.client, data) - break - default: - throw new Error(`Unknown channel type: ${data.channel_type}`) - } + _add(data: APIChannel): ServerChannel { + let channel: ServerChannel; - this.cache.set(channel.id, channel) - - return channel + switch (data.channel_type) { + case 'TextChannel': + channel = new TextChannel(this.client, data); + break; + case 'VoiceChannel': + channel = new VoiceChannel(this.client, data); + break; + default: + throw new Error(`Unknown channel type: ${data.channel_type}`); } - async create({ name, type = 'Text', description }: CreateChannelOptions): Promise { - const data = await this.client.api.post(`/servers/${this.server.id}/channels`, { - body: { - name, - type, - description, - nonce: UUID.generate() - } - }) - return this._add(data) - } + this.cache.set(channel.id, channel); - async fetch(channel: ServerChannelResolvable, { force = true } = {}): Promise { - const id = this.resolveId(channel) + return channel; + } - if (!id) throw new TypeError('INVALID_TYPE', 'channel', 'ServerChannelResolvable') + async create( + { name, type = 'Text', description }: CreateChannelOptions, + ): Promise { + const data = await this.client.api.post( + `/servers/${this.server.id}/channels`, + { + body: { + name, + type, + description, + nonce: UUID.generate(), + }, + }, + ); + return this._add(data); + } - if (!force) { - const channel = this.cache.get(id) - if (channel) return channel - } + async fetch( + channel: ServerChannelResolvable, + { force = true } = {}, + ): Promise { + const id = this.resolveId(channel); - const data = await this.client.api.get(`/servers/${this.server.id}/channels/${id}`) + if (!id) { + throw new TypeError('INVALID_TYPE', 'channel', 'ServerChannelResolvable'); + } - return this._add(data) + if (!force) { + const channel = this.cache.get(id); + if (channel) return channel; } + + const data = await this.client.api.get( + `/servers/${this.server.id}/channels/${id}`, + ); + + return this._add(data); + } } diff --git a/src/managers/ServerManager.ts b/src/managers/ServerManager.ts index a44f79f..618ca44 100644 --- a/src/managers/ServerManager.ts +++ b/src/managers/ServerManager.ts @@ -1,69 +1,75 @@ -import type { Server as APIServer } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Server } from '../structures/index' -import { UUID } from '../util/index' +import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Server } from '../structures/mod.ts'; +import { UUID } from '../util/mod.ts'; -export type ServerResolvable = Server | APIServer | string +export type ServerResolvable = Server | APIServer | string; export interface EditServerOptions { - name?: string - description?: string + name?: string; + description?: string; } export class ServerManager extends BaseManager { - readonly holds = Server + readonly holds = Server; - _remove(id: string): void { - const server = this.cache.get(id) + _remove(id: string): void { + const server = this.cache.get(id); - for (const id of server?.channels.cache.keys() ?? []) { - this.client.channels._remove(id) - } - - return super._remove(id) - } - - async create(name: string): Promise { - const { server } = await this.client.api.post('/servers/create', { - body: { - name, - nonce: UUID.generate() - } - }) - return this._add(server) + for (const id of server?.channels.cache.keys() ?? []) { + this.client.channels._remove(id); } - async edit(server: ServerResolvable, options: EditServerOptions): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.patch(`/servers/${id}`, { body: options }) - } + return super._remove(id); + } - async ack(server: ServerResolvable): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.put(`/servers/${id}/ack`) - } + async create(name: string): Promise { + const { server } = await this.client.api.post('/servers/create', { + body: { + name, + nonce: UUID.generate(), + }, + }); + return this._add(server); + } - async delete(server: ServerResolvable): Promise { - const id = this.resolveId(server) - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') - await this.client.api.delete(`/servers/${id}`) - } + async edit( + server: ServerResolvable, + options: EditServerOptions, + ): Promise { + const id = this.resolveId(server); + if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable'); + await this.client.api.patch(`/servers/${id}`, { body: options }); + } - async fetch(server: ServerResolvable, { force = true } = {}): Promise { - const id = this.resolveId(server) + async ack(server: ServerResolvable): Promise { + const id = this.resolveId(server); + if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable'); + await this.client.api.put(`/servers/${id}/ack`); + } - if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable') + async delete(server: ServerResolvable): Promise { + const id = this.resolveId(server); + if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable'); + await this.client.api.delete(`/servers/${id}`); + } - if (!force) { - const server = this.cache.get(id) - if (server) return server - } + async fetch( + server: ServerResolvable, + { force = true } = {}, + ): Promise { + const id = this.resolveId(server); - const data = (await this.client.api.get(`/servers/${id}`)) as APIServer + if (!id) throw new TypeError('INVALID_TYPE', 'server', 'ServerResolvable'); - return this._add(data) + if (!force) { + const server = this.cache.get(id); + if (server) return server; } + + const data = await this.client.api.get(`/servers/${id}`); + + return this._add(data); + } } diff --git a/src/managers/ServerMemberManager.ts b/src/managers/ServerMemberManager.ts index 1df7a6c..772e03f 100644 --- a/src/managers/ServerMemberManager.ts +++ b/src/managers/ServerMemberManager.ts @@ -1,71 +1,96 @@ -import type { Member as APIMember } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Server, ServerMember, User } from '../structures/index' -import { Collection } from '../util/index' +import type { Member as APIMember } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Server, ServerMember, User } from '../structures/mod.ts'; +import { Collection } from '../util/mod.ts'; -export type ServerMemberResolvable = ServerMember | User | APIMember | string +export type ServerMemberResolvable = ServerMember | User | APIMember | string; export interface EditServerMemberOptions { - nickname?: string - avatar?: string - roles?: string[] + nickname?: string; + avatar?: string; + roles?: string[]; } export class ServerMemberManager extends BaseManager { - holds = ServerMember - constructor(protected readonly server: Server) { - super(server.client) - } + holds = ServerMember; + constructor(protected readonly server: Server) { + super(server.client); + } - async edit(member: ServerMemberResolvable, options: EditServerMemberOptions): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.patch(`/servers/${this.server.id}/members/${id}`, { body: { ...options } }) + async edit( + member: ServerMemberResolvable, + options: EditServerMemberOptions, + ): Promise { + const id = this.resolveId(member); + if (!id) { + throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable'); } + await this.client.api.patch(`/servers/${this.server.id}/members/${id}`, { + body: { ...options }, + }); + } - async ban(member: ServerMemberResolvable, reason?: string): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.put(`/servers/${this.server.id}/bans/${id}`, { body: { reason } }) + async ban(member: ServerMemberResolvable, reason?: string): Promise { + const id = this.resolveId(member); + if (!id) { + throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable'); } + await this.client.api.put(`/servers/${this.server.id}/bans/${id}`, { + body: { reason }, + }); + } - async kick(member: ServerMemberResolvable): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.delete(`/servers/${this.server.id}/members/${id}`) + async kick(member: ServerMemberResolvable): Promise { + const id = this.resolveId(member); + if (!id) { + throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable'); } + await this.client.api.delete(`/servers/${this.server.id}/members/${id}`); + } - async unban(member: ServerMemberResolvable): Promise { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - await this.client.api.delete(`/servers/${this.server.id}/bans/${id}`) + async unban(member: ServerMemberResolvable): Promise { + const id = this.resolveId(member); + if (!id) { + throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable'); } + await this.client.api.delete(`/servers/${this.server.id}/bans/${id}`); + } - async fetch(member: ServerMemberResolvable): Promise - async fetch(): Promise> - async fetch(member?: ServerMemberResolvable): Promise> { - if (typeof member !== 'undefined') { - const id = this.resolveId(member) - if (!id) throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable') - const data = await this.client.api.get(`/servers/${this.server.id}/members/${id}`) - return this._add(data) - } + async fetch(member: ServerMemberResolvable): Promise; + async fetch(): Promise>; + async fetch( + member?: ServerMemberResolvable, + ): Promise> { + if (typeof member !== 'undefined') { + const id = this.resolveId(member); + if (!id) { + throw new TypeError('INVALID_TYPE', 'member', 'ServerMemberResolvable'); + } + const data = await this.client.api.get( + `/servers/${this.server.id}/members/${id}`, + ); + return this._add(data); + } - const { members } = (await this.client.api.get(`/servers/${this.server.id}/members`)) as { members: APIMember[] } + const { members } = await this.client.api.get( + `/servers/${this.server.id}/members`, + ); - return members.reduce((coll, cur) => { - const member = this._add(cur) - coll.set(member.id, member) - return coll - }, new Collection()) - } + return members.reduce((coll, cur) => { + const member = this._add(cur); + coll.set(member.id, member); + return coll; + }, new Collection()); + } - resolveId(member: ServerMemberResolvable): string | null { - if (member == null) return null - if (member instanceof ServerMember || member instanceof User) return member.id - if (typeof member === 'string') return member - if ('_id' in member) return member._id.user - return null + resolveId(member: ServerMemberResolvable): string | null { + if (member == null) return null; + if (member instanceof ServerMember || member instanceof User) { + return member.id; } + if (typeof member === 'string') return member; + if ('_id' in member) return member._id.user; + return null; + } } diff --git a/src/managers/UserManager.ts b/src/managers/UserManager.ts index 72b7fc2..7fd26ba 100644 --- a/src/managers/UserManager.ts +++ b/src/managers/UserManager.ts @@ -1,37 +1,37 @@ -import type { User as APIUser } from 'revolt-api' -import { BaseManager } from './BaseManager' -import { TypeError } from '../errors/index' -import { Message, User } from '../structures/index' +import type { User as APIUser } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { BaseManager } from './BaseManager.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Message, User } from '../structures/mod.ts'; -export type UserResolvable = User | APIUser | Message | string +export type UserResolvable = User | APIUser | Message | string; export class UserManager extends BaseManager { - holds = User + holds = User; - async fetch(user: UserResolvable, { force = true } = {}): Promise { - const userId = this.resolveId(user) + async fetch(user: UserResolvable, { force = true } = {}): Promise { + const id = this.resolveId(user); - if (!userId) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') + if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); - if (!force) { - const user = this.cache.get(userId) - if (user) return user - } + if (!force) { + const user = this.cache.get(id); + if (user) return user; + } - const data = (await this.client.api.get(`/users/${userId}`)) as APIUser + const data = await this.client.api.get(`/users/${id}`) as APIUser; - return this._add(data) - } + return this._add(data); + } - resolve(resolvable: Message | User): User - resolve(resolvable: string | APIUser): User | null - resolve(resolvable: User | APIUser | string | Message): User | null { - if (resolvable instanceof Message) return resolvable.author - return super.resolve(resolvable) - } + resolve(resolvable: Message | User): User; + resolve(resolvable: string | APIUser): User | null; + resolve(resolvable: User | APIUser | string | Message): User | null { + if (resolvable instanceof Message) return resolvable.author; + return super.resolve(resolvable); + } - resolveId(resolvable: UserResolvable): string | null { - if (resolvable instanceof Message) return resolvable.authorId - return super.resolveId(resolvable) - } + resolveId(resolvable: UserResolvable): string | null { + if (resolvable instanceof Message) return resolvable.authorId; + return super.resolveId(resolvable); + } } diff --git a/src/managers/index.ts b/src/managers/index.ts deleted file mode 100644 index e3a9153..0000000 --- a/src/managers/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './BaseManager' -export * from './ChannelManager' -export * from './MessageManager' -export * from './RoleManager' -export * from './ServerChannelManager' -export * from './ServerMemberManager' -export * from './ServerManager' -export * from './UserManager' diff --git a/src/managers/mod.ts b/src/managers/mod.ts new file mode 100644 index 0000000..87acb17 --- /dev/null +++ b/src/managers/mod.ts @@ -0,0 +1,8 @@ +export * from './BaseManager.ts'; +export * from './ChannelManager.ts'; +export * from './MessageManager.ts'; +export * from './RoleManager.ts'; +export * from './ServerChannelManager.ts'; +export * from './ServerMemberManager.ts'; +export * from './ServerManager.ts'; +export * from './UserManager.ts'; diff --git a/src/rest/APIRequest.ts b/src/rest/APIRequest.ts deleted file mode 100644 index 4ca8f97..0000000 --- a/src/rest/APIRequest.ts +++ /dev/null @@ -1,41 +0,0 @@ -import fetch, { Response, HeadersInit } from 'node-fetch' - -export interface APIRequestOptions { - method?: RequestMethod - body?: unknown - headers?: HeadersInit - timeout?: number -} - -export enum RequestMethod { - Delete = 'DELETE', - Get = 'GET', - Patch = 'PATCH', - Post = 'POST', - Put = 'PUT' -} - -export class APIRequest { - body?: unknown - headers?: HeadersInit - method = RequestMethod.Get - retries = 0 - timeout: number - constructor(public path: string, { method, headers, body, timeout }: APIRequestOptions = {}) { - this.method = method ?? this.method - this.body = body - this.headers = headers - this.timeout = timeout ?? 0 - } - - execute(): Promise { - const controller = new AbortController() - const timeout = setTimeout(() => controller.abort(), this.timeout) - return fetch(this.path, { - method: this.method, - body: this.body ? JSON.stringify(this.body) : null, - headers: this.headers, - signal: controller.signal - }).finally(() => clearTimeout(timeout)) - } -} diff --git a/src/rest/Endpoints.ts b/src/rest/Endpoints.ts deleted file mode 100644 index 76c3ecb..0000000 --- a/src/rest/Endpoints.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { BaseClientOptions } from '../client/index' - -export type EndpointsOptions = BaseClientOptions['endpoints'] - -export class Endpoints { - constructor(private readonly options: EndpointsOptions) {} - - get CDN(): string { - return this.options.cdn - } - - get INVITE(): string { - return this.options.invite - } - - get API(): string { - return this.options.api - } - - defaultAvatar(id: string): string { - return `${this.API}/users/${id}/default_avatar` - } - - avatar(hash: string, filename: string, size = 1024): string { - return `${this.CDN}/avatars/${hash}/${filename}?max_side=${size}` - } - - icon(hash: string, size = 1024): string { - return `${this.CDN}/icons/${hash}?max_side=${size}` - } - - invite(code: string): string { - return `${this.INVITE}/${code}` - } - - banner(hash: string, size = 1024): string { - return `${this.CDN}/banners/${hash}?max_side=${size}` - } -} diff --git a/src/rest/HTTPError.ts b/src/rest/HTTPError.ts deleted file mode 100644 index 537cc0c..0000000 --- a/src/rest/HTTPError.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { APIRequest, RequestMethod } from './APIRequest' - -export class HTTPError extends Error { - code: number - method: RequestMethod - path: string - constructor(message: string, name: string, code: number, request: APIRequest) { - super(message) - this.name = name - this.code = code ?? 500 - this.method = request.method - this.path = request.path - } -} diff --git a/src/rest/REST.ts b/src/rest/REST.ts deleted file mode 100644 index 8c84309..0000000 --- a/src/rest/REST.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -/* eslint-disable @typescript-eslint/no-empty-function */ -import { Response } from 'node-fetch' -import type { APIRoutes } from 'revolt-api/dist/routes' -import { APIRequest, APIRequestOptions, RequestMethod } from './APIRequest' -import { HTTPError } from './HTTPError' -import { BaseClientOptions } from '../client/BaseClient' - -type GetRoutes = Extract -type PostRoutes = Extract -type DeleteRoutes = Extract -type PatchRoutes = Extract -type PutRoutes = Extract - -export const parseResponse = (res: Response): Promise => { - if (res.headers.get('Content-Type')?.startsWith('application/json')) { - return res.json() - } - return res.arrayBuffer() -} - -export type RESTOptions = BaseClientOptions['rest'] - -export class REST { - #token: string | null = null - #bot = true - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - debug(_message: string) {} - constructor(private readonly options: RESTOptions) {} - - setToken(token: string | null, bot = true): this { - this.#token = token - this.#bot = bot - return this - } - - private get headers() { - if (!this.#token) return {} - return { - [`x-${this.#bot ? 'bot' : 'session'}-token`]: this.#token - } - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async request(request: APIRequest): Promise { - let res: Response - - try { - res = await request.execute() - } catch (error) { - if (request.retries === this.options.retries) { - if (error instanceof Response) { - throw new HTTPError(error.statusText, error.constructor.name, error.status, request) - } - } - - request.retries++ - return this.request(request) - } - - if (res.ok) { - return parseResponse(res) - } - - // TODO: Handle ratelimit - if (res.status === 429) { - this.debug(`Hit a 429 while executing a request. - Method: ${request.method} - Path: ${request.path} - Limit: ${this.options.retries} - Timeout: ${this.options.timeout}ms`) - } - - if (res.status >= 500 && res.status < 600) { - if (request.retries === this.options.retries) { - throw new HTTPError(res.statusText, res.constructor.name, res.status, request) - } - - request.retries++ - - return this.request(request) - } - - throw new HTTPError(res.statusText, res.constructor.name, res.status, request) - } - - private getOptions(options: APIRequestOptions, method: RequestMethod) { - return { - ...options, - headers: this.headers, - timeout: this.options.timeout, - method - } - } - - get(path: Path, options: APIRequestOptions = {}): Promise['response']> { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Get))) - } - - delete( - path: Path, - options: APIRequestOptions = {} - ): Promise['response']> { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Delete))) - } - - post(path: Path, options: APIRequestOptions = {}): Promise['response']> { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Post))) - } - - put(path: Path, options: APIRequestOptions = {}): Promise['response']> { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Put))) - } - - patch(path: Path, options: APIRequestOptions = {}): Promise['response']> { - return this.request(new APIRequest(this.options.url + path, this.getOptions(options, RequestMethod.Patch))) - } -} diff --git a/src/rest/index.ts b/src/rest/index.ts deleted file mode 100644 index c4d2a01..0000000 --- a/src/rest/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './REST' -export * from './Endpoints' diff --git a/src/structures/Base.ts b/src/structures/Base.ts index b503bd7..cc86546 100644 --- a/src/structures/Base.ts +++ b/src/structures/Base.ts @@ -1,27 +1,27 @@ -import type { Client } from '../client/Client' +import type { Client } from '../client/Client.ts'; -type ID = { _id: string } | { id: string } | { _id: { user: string } } +type ID = { _id: string } | { id: string } | { _id: { user: string } }; export abstract class Base = Partial> { - id!: string - constructor(public readonly client: Client) {} + id!: string; + constructor(public readonly client: Client) {} - _update(data: APIBase): this { - const clone = this._clone() - clone._patch(data) - return clone - } + _update(data: APIBase): this { + const clone = this._clone(); + clone._patch(data); + return clone; + } - protected _patch(data: APIBase): this { - if ('id' in data) this.id = data.id! - if ('_id' in data) { - if (typeof data._id === 'string') this.id = data._id - if (typeof data._id === 'object') this.id = data._id.user - } - return this + protected _patch(data: APIBase): this { + if ('id' in data) this.id = data.id!; + if ('_id' in data) { + if (typeof data._id === 'string') this.id = data._id; + if (typeof data._id === 'object') this.id = data._id.user; } + return this; + } - protected _clone(): this { - return Object.assign(Object.create(this), this) - } + protected _clone(): this { + return Object.assign(Object.create(this), this); + } } diff --git a/src/structures/Category.ts b/src/structures/Category.ts index 5e59470..61c51b0 100644 --- a/src/structures/Category.ts +++ b/src/structures/Category.ts @@ -1,41 +1,41 @@ -import type { Category as APICategory } from 'revolt-api' -import { Base, Server, ServerChannel } from './index' -import { Collection } from '../util/index' +import type { Category as APICategory } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Base, Server, ServerChannel } from './mod.ts'; +import { Collection } from '../util/mod.ts'; export class Category extends Base { - name!: string - protected _children: string[] = [] - constructor(public server: Server, data: APICategory) { - super(server.client) - this._patch(data) + name!: string; + protected _children: string[] = []; + constructor(public server: Server, data: APICategory) { + super(server.client); + this._patch(data); + } + + protected _patch(data: APICategory): this { + super._patch(data); + + if (data.title) { + this.name = data.title; } - protected _patch(data: APICategory): this { - super._patch(data) - - if (data.title) { - this.name = data.title - } - - if (Array.isArray(data.channels)) { - this._children = data.channels - } - - return this + if (Array.isArray(data.channels)) { + this._children = data.channels; } - get children(): Collection { - const coll = new Collection() + return this; + } - for (const childId of this._children) { - const child = this.server.channels.cache.get(childId) - if (child) coll.set(child.id, child) - } + get children(): Collection { + const coll = new Collection(); - return coll + for (const childId of this._children) { + const child = this.server.channels.cache.get(childId); + if (child) coll.set(child.id, child); } - toString(): string { - return this.name - } + return coll; + } + + toString(): string { + return this.name; + } } diff --git a/src/structures/Channel.ts b/src/structures/Channel.ts index 7fccf62..30ded30 100644 --- a/src/structures/Channel.ts +++ b/src/structures/Channel.ts @@ -1,72 +1,51 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Base, DMChannel, GroupChannel, NotesChannel, ServerChannel, TextChannel, VoiceChannel } from './index' -import type { Client } from '../client/Client' -import { ChannelTypes, UUID } from '../util/index' - -export abstract class Channel extends Base { - type: ChannelTypes | 'UNKNOWN' = 'UNKNOWN' - - constructor(client: Client, data: T) { - super(client) - this._patch(data) - } - - static create(client: Client, data: APIChannel): Channel { - let channel: Channel - - switch (data.channel_type) { - case 'TextChannel': - channel = new TextChannel(client, data) - break - case 'VoiceChannel': - channel = new VoiceChannel(client, data) - break - case 'DirectMessage': - channel = new DMChannel(client, data) - break - case 'Group': - channel = new GroupChannel(client, data) - break - case 'SavedMessages': - channel = new NotesChannel(client, data) - break - } - - return channel - } - get createdTimestamp(): number { - return this.createdAt.getTime() - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - async delete(): Promise { - await this.client.channels.delete(this) - } - - isText(): this is TextChannel | GroupChannel | DMChannel { - return 'messages' in this - } - - isVoice(): this is VoiceChannel { - return this.type === ChannelTypes.VOICE - } - - isGroup(): this is GroupChannel { - return this.type === ChannelTypes.GROUP - } - - inServer(): this is ServerChannel { - return 'serverId' in this - } - - toString(): string { - return `<#${this.id}>` - } - - fetch(force = true): Promise { - return this.client.channels.fetch(this, { force }) - } +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { + Base, + DMChannel, + GroupChannel, + ServerChannel, + TextChannel, + VoiceChannel, +} from './mod.ts'; +import { ChannelTypes, UUID } from '../util/mod.ts'; + +export abstract class Channel + extends Base { + type: ChannelTypes | 'UNKNOWN' = 'UNKNOWN'; + + get createdTimestamp(): number { + return this.createdAt.getTime(); + } + + get createdAt(): Date { + return UUID.timestampOf(this.id); + } + + async delete(): Promise { + await this.client.channels.delete(this); + } + + isText(): this is TextChannel | GroupChannel | DMChannel { + return 'messages' in this; + } + + isVoice(): this is VoiceChannel { + return this.type === ChannelTypes.VOICE; + } + + isGroup(): this is GroupChannel { + return this.type === ChannelTypes.GROUP; + } + + inServer(): this is ServerChannel { + return 'serverId' in this; + } + + toString(): string { + return `<#${this.id}>`; + } + + fetch(force = true): Promise { + return this.client.channels.fetch(this, { force }); + } } diff --git a/src/structures/ClientUser.ts b/src/structures/ClientUser.ts index 47aded5..1b55dcd 100644 --- a/src/structures/ClientUser.ts +++ b/src/structures/ClientUser.ts @@ -1,16 +1,21 @@ -import type { NotesChannel } from './index' -import { User } from './User' +import type { NotesChannel } from './mod.ts'; +import { User } from './User.ts'; export class ClientUser extends User { - notes: NotesChannel | null = null + notes: NotesChannel | null = null; - async setUsername(username: string, password?: string): Promise { - await this.client.api.patch('/users/@me/username', { - body: { username, password } - }) - } + async setUsername(username: string, password?: string): Promise { + await this.client.api.patch('/users/@me/username', { + body: { username, password }, + }); + } - async setStatus(status: { text?: string; presence?: 'Online' | 'Idle' | 'Busy' | 'Invisible' }): Promise { - await this.client.api.patch('/users/@me', { body: { status } }) - } + async setStatus( + status: { + text?: string; + presence?: 'Online' | 'Idle' | 'Busy' | 'Invisible'; + }, + ): Promise { + await this.client.api.patch('/users/@me', { body: { status } }); + } } diff --git a/src/structures/DMChannel.ts b/src/structures/DMChannel.ts index 85f1910..a5b8914 100644 --- a/src/structures/DMChannel.ts +++ b/src/structures/DMChannel.ts @@ -1,37 +1,38 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Channel, Message } from './index' -import { TextBasedChannel } from './interfaces/index' -import { Client, MessageManager, MessageOptions } from '../index' -import { ChannelTypes, DEFAULT_PERMISSION_DM } from '../util/index' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Channel, Message } from './mod.ts'; +import { TextBasedChannel } from './interfaces/mod.ts'; +import { Client, MessageManager, MessageOptions } from '../lib.ts'; +import { ChannelTypes, DEFAULT_PERMISSION_DM } from '../util/mod.ts'; -type APIDirectChannel = Extract +type APIDirectChannel = Extract; -export class DMChannel extends Channel implements TextBasedChannel { - readonly type = ChannelTypes.DM - active!: boolean - permissions = DEFAULT_PERMISSION_DM - messages = new MessageManager(this) - lastMessageId: string | null = null +export class DMChannel extends Channel + implements TextBasedChannel { + readonly type = ChannelTypes.DM; + active!: boolean; + permissions = DEFAULT_PERMISSION_DM; + messages = new MessageManager(this); + lastMessageId: string | null = null; - constructor(client: Client, data: APIDirectChannel) { - super(client, data) - this._patch(data) - } + constructor(client: Client, data: APIDirectChannel) { + super(client); + this._patch(data); + } - protected _patch(data: APIDirectChannel): this { - super._patch(data) + protected _patch(data: APIDirectChannel): this { + super._patch(data); - if (typeof data.active === 'boolean') this.active = data.active - if (data.last_message_id) this.lastMessageId = data.last_message_id + if (typeof data.active === 'boolean') this.active = data.active; + if (data.last_message_id) this.lastMessageId = data.last_message_id; - return this - } - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } + return this; + } + send(options: MessageOptions | string): Promise { + return this.messages.send(options); + } - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } + get lastMessage(): Message | null { + if (!this.lastMessageId) return null; + return this.messages.cache.get(this.lastMessageId) ?? null; + } } diff --git a/src/structures/GroupChannel.ts b/src/structures/GroupChannel.ts index 7245490..78d948d 100644 --- a/src/structures/GroupChannel.ts +++ b/src/structures/GroupChannel.ts @@ -1,96 +1,102 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { User, Channel, Message } from './index' -import { TextBasedChannel } from './interfaces/index' -import type { Client } from '../client/Client' -import { TypeError } from '../errors/index' -import { MessageManager, MessageOptions, UserResolvable } from '../managers/index' -import { ChannelPermissions, ChannelTypes, Collection } from '../util/index' - -type APIGroupChannel = Extract - -export class GroupChannel extends Channel implements TextBasedChannel { - name!: string - description: string | null = null - ownerId!: string - readonly type = ChannelTypes.GROUP - permissions!: Readonly - icon: string | null = null - messages = new MessageManager(this) - lastMessageId: string | null = null - users = new Collection() - nsfw = false - - constructor(client: Client, data: APIGroupChannel) { - super(client, data) - this._patch(data) +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import type { Message, User } from './mod.ts'; +import type { TextBasedChannel } from './interfaces/mod.ts'; +import type { Client } from '../client/Client.ts'; +import { TypeError } from '../errors/mod.ts'; +import { Channel } from './Channel.ts'; +import { + MessageManager, + MessageOptions, + UserResolvable, +} from '../managers/mod.ts'; +import { ChannelPermissions, ChannelTypes, Collection } from '../util/mod.ts'; + +type APIGroupChannel = Extract; + +export class GroupChannel extends Channel + implements TextBasedChannel { + name!: string; + description: string | null = null; + ownerId!: string; + readonly type = ChannelTypes.GROUP; + permissions!: Readonly; + icon: string | null = null; + messages = new MessageManager(this); + lastMessageId: string | null = null; + users = new Collection(); + nsfw = false; + + constructor(client: Client, data: APIGroupChannel) { + super(client); + this._patch(data); + } + + protected _patch(data: APIGroupChannel): this { + super._patch(data); + + if ('description' in data) { + this.description = data.description ?? null; } - protected _patch(data: APIGroupChannel): this { - super._patch(data) - - if ('description' in data) { - this.description = data.description ?? null - } - - if (Array.isArray(data.recipients)) { - this.users.clear() - for (const userId of data.recipients) { - const user = this.client.users.cache.get(userId) - if (user) this.users.set(user.id, user) - } - } - - if (typeof data.permissions === 'number') { - this.permissions = new ChannelPermissions(data.permissions).freeze() - } - - if (data.owner) { - this.ownerId = data.owner - } - - if ('icon' in data) { - this.icon = data.icon?._id ?? null - } - - if (data.name) { - this.name = data.name - } - - if (data.last_message_id) this.lastMessageId = data.last_message_id - - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - - return this + if (Array.isArray(data.recipients)) { + this.users.clear(); + for (const userId of data.recipients) { + const user = this.client.users.cache.get(userId); + if (user) this.users.set(user.id, user); + } } - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null + if (typeof data.permissions === 'number') { + this.permissions = new ChannelPermissions(data.permissions).freeze(); } - async add(user: UserResolvable): Promise { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - await this.client.api.put(`/channels/${this.id}/recipients/${id}`) - } - async remove(user: UserResolvable): Promise { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - await this.client.api.delete(`/channels/${this.id}/recipients/${id}`) - } - async leave(): Promise { - await super.delete() - } - send(options: MessageOptions | string): Promise { - return this.messages.send(options) + if (data.owner) { + this.ownerId = data.owner; } - iconURL(options?: { size: number }): string | null { - if (!this.icon) return null - return this.client.endpoints.icon(this.icon, options?.size) + if ('icon' in data) { + this.icon = data.icon?._id ?? null; } - get owner(): User | null { - return this.client.users.cache.get(this.ownerId) ?? null + if (data.name) { + this.name = data.name; } + + if (data.last_message_id) this.lastMessageId = data.last_message_id; + + if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw; + + return this; + } + + get lastMessage(): Message | null { + if (!this.lastMessageId) return null; + return this.messages.cache.get(this.lastMessageId) ?? null; + } + + async add(user: UserResolvable): Promise { + const id = this.client.users.resolveId(user); + if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + await this.client.api.put(`/channels/${this.id}/recipients/${id}`); + } + async remove(user: UserResolvable): Promise { + const id = this.client.users.resolveId(user); + if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + await this.client.api.delete(`/channels/${this.id}/recipients/${id}`); + } + async leave(): Promise { + await super.delete(); + } + send(options: MessageOptions | string): Promise { + return this.messages.send(options); + } + + iconURL(options?: { size: number }): string | null { + if (!this.icon) return null; + return this.client.api.cdn.icon(this.icon, options?.size); + } + + get owner(): User | null { + return this.client.users.cache.get(this.ownerId) ?? null; + } } diff --git a/src/structures/Mentions.ts b/src/structures/Mentions.ts index 3319a64..13a56b2 100644 --- a/src/structures/Mentions.ts +++ b/src/structures/Mentions.ts @@ -1,45 +1,45 @@ -import { Message, ServerMember, User } from './index' -import { Client } from '../client/Client' -import { TypeError } from '../errors/index' -import { UserResolvable } from '../managers/index' -import { Collection } from '../util/index' +import { Message, ServerMember, User } from './mod.ts'; +import { Client } from '../client/Client.ts'; +import { TypeError } from '../errors/mod.ts'; +import { UserResolvable } from '../managers/mod.ts'; +import { Collection } from '../util/mod.ts'; export class Mentions { - public readonly client: Client + public readonly client: Client; - constructor(public message: Message, protected _users: string[]) { - this.client = message.client - } - - has(user: UserResolvable): boolean { - const id = this.client.users.resolveId(user) - if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable') - return this._users.includes(id) - } + constructor(public message: Message, protected _users: string[]) { + this.client = message.client; + } - get members(): Collection | null { - const server = this.message.server + has(user: UserResolvable): boolean { + const id = this.client.users.resolveId(user); + if (!id) throw new TypeError('INVALID_TYPE', 'user', 'UserResolvable'); + return this._users.includes(id); + } - if (!server) return null + get members(): Collection | null { + const server = this.message.server; - const members = new Collection() + if (!server) return null; - for (const userId of this._users) { - const member = server.members.cache.get(userId) - if (member) members.set(member.id, member) - } + const members = new Collection(); - return members + for (const userId of this._users) { + const member = server.members.cache.get(userId); + if (member) members.set(member.id, member); } - get users(): Collection { - const users = new Collection() + return members; + } - for (const userId of this._users) { - const user = this.client.users.cache.get(userId) - if (user) users.set(user.id, user) - } + get users(): Collection { + const users = new Collection(); - return users + for (const userId of this._users) { + const user = this.client.users.cache.get(userId); + if (user) users.set(user.id, user); } + + return users; + } } diff --git a/src/structures/Message.ts b/src/structures/Message.ts index b7e2a34..124db85 100644 --- a/src/structures/Message.ts +++ b/src/structures/Message.ts @@ -1,125 +1,147 @@ -import type { Message as APIMessage, SystemMessage, Embed, File } from 'revolt-api' -import { Base, DMChannel, GroupChannel, Mentions, Server, ServerMember, TextChannel, User } from './index' -import { Client } from '../client/Client' -import { UUID } from '../util/index' +import type { + Embed, + File, + Message as APIMessage, + SystemMessage, +} from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { + Base, + DMChannel, + GroupChannel, + Mentions, + Server, + ServerMember, + TextChannel, + User, +} from './mod.ts'; +import { Client } from '../client/Client.ts'; +import { UUID } from '../util/mod.ts'; export class Message extends Base { - content = '' - channelId!: string - authorId!: string - embeds: Embed[] = [] - attachments: File[] = [] - mentions = new Mentions(this, []) - type: Uppercase = 'TEXT' - editedAt: Date | null = null - constructor(client: Client, data: APIMessage) { - super(client) - this._patch(data) - } - - protected _patch(data: APIMessage): this { - super._patch(data) - - if (Array.isArray(data.embeds)) { - this.embeds = data.embeds - } - - if (Array.isArray(data.attachments)) { - this.attachments = data.attachments - } - - if (Array.isArray(data.mentions)) { - this.mentions = new Mentions(this, data.mentions) - } - - if (data.author) { - this.authorId = data.author - } - - if (data.channel) { - this.channelId = data.channel - } + content = ''; + channelId!: string; + authorId!: string; + embeds: Embed[] = []; + attachments: File[] = []; + mentions = new Mentions(this, []); + type: Uppercase = 'TEXT'; + editedAt: Date | null = null; + constructor(client: Client, data: APIMessage) { + super(client); + this._patch(data); + } - if (typeof data.content === 'string') { - this.content = data.content - } + protected _patch(data: APIMessage): this { + super._patch(data); - if (data.system) { - this.type = data.system.type.toUpperCase() as Uppercase - } - - if (data.edited) { - this.editedAt = new Date(data.edited) - } - - return this + if (Array.isArray(data.embeds)) { + this.embeds = data.embeds; } - get createdAt(): Date { - return UUID.timestampOf(this.id) + if (Array.isArray(data.attachments)) { + this.attachments = data.attachments; } - get createdTimestamp(): number { - return this.createdAt.getTime() + if (Array.isArray(data.mentions)) { + this.mentions = new Mentions(this, data.mentions); } - get editedTimestamp(): number | null { - return this.editedAt?.getTime() ?? null + if (data.author) { + this.authorId = data.author; } - async ack(): Promise { - await this.channel.messages.ack(this) + if (data.channel) { + this.channelId = data.channel; } - async delete(): Promise { - await this.channel.messages.delete(this) + if (typeof data.content === 'string') { + this.content = data.content; } - async reply(content: string, mention = true): Promise { - return this.channel.messages.send({ - content, - replies: [{ id: this.id, mention }] - }) + if (data.system) { + this.type = data.system.type.toUpperCase() as Uppercase< + SystemMessage['type'] + >; } - async edit(content: string): Promise { - await this.channel.messages.edit(this, { content }) + if (data.edited) { + this.editedAt = new Date(data.edited); } - fetch(): Promise { - return this.channel.messages.fetch(this.id) - } + return this; + } - get system(): boolean { - return this.type !== 'TEXT' - } + get createdAt(): Date { + return UUID.timestampOf(this.id); + } - inServer(): this is this & { serverId: string; server: Server; channel: TextChannel } { - return this.channel.inServer() - } + get createdTimestamp(): number { + return this.createdAt.getTime(); + } - get author(): User | null { - return this.client.users.cache.get(this.authorId) ?? null - } + get editedTimestamp(): number | null { + return this.editedAt?.getTime() ?? null; + } - get channel(): TextChannel | DMChannel | GroupChannel { - return this.client.channels.cache.get(this.channelId) as TextChannel - } + async ack(): Promise { + await this.channel.messages.ack(this); + } - get serverId(): string | null { - const channel = this.channel - return channel.inServer() ? channel.serverId : null - } + async delete(): Promise { + await this.channel.messages.delete(this); + } - get server(): Server | null { - return this.client.servers.cache.get(this.serverId as string) ?? null - } + reply(content: string, mention = true): Promise { + return this.channel.messages.send({ + content, + replies: [{ id: this.id, mention }], + }); + } - get member(): ServerMember | null { - return this.server?.members.cache.get(this.authorId) ?? null - } + async edit(content: string): Promise { + await this.channel.messages.edit(this, { content }); + } - get url(): string { - return `https://app.revolt.chat/${this.serverId ? `server/${this.serverId}` : ''}/channel/${this.channelId}/${this.id}` - } + fetch(): Promise { + return this.channel.messages.fetch(this.id); + } + + get system(): boolean { + return this.type !== 'TEXT'; + } + + inServer(): this is this & { + serverId: string; + server: Server; + channel: TextChannel; + } { + return this.channel.inServer(); + } + + get author(): User | null { + return this.client.users.cache.get(this.authorId) ?? null; + } + + get channel(): TextChannel | DMChannel | GroupChannel { + return this.client.channels.cache.get(this.channelId) as TextChannel; + } + + get serverId(): string | null { + const channel = this.channel; + return channel.inServer() ? channel.serverId : null; + } + + get server(): Server | null { + return this.client.servers.cache.get(this.serverId as string) ?? null; + } + + get member(): ServerMember | null { + return this.server?.members.cache.get(this.authorId) ?? null; + } + + get url(): string { + return `https://app.revolt.chat/${ + this.serverId ? `server/${this.serverId}` : '' + }/channel/${this.channelId}/${this.id}`; + } } diff --git a/src/structures/MessageEmbed.ts b/src/structures/MessageEmbed.ts index fb8fdc5..2010a32 100644 --- a/src/structures/MessageEmbed.ts +++ b/src/structures/MessageEmbed.ts @@ -1,56 +1,59 @@ -import type { Embed, Special } from 'revolt-api' +import type { + Embed, + Special, +} from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; -export type EmbedImage = Extract -export type EmbedVideo = Extract -export type EmbedSpecial = Special +export type EmbedImage = Extract; +export type EmbedVideo = Extract; +export type EmbedSpecial = Special; export class MessageEmbed { - type: Embed['type'] = 'Website' - url?: string - special?: EmbedSpecial - title?: string - description?: string - image?: EmbedImage - video?: EmbedVideo - site_name?: string - icon_url?: string - color?: string - - constructor(data: Partial = {}) { - Object.assign(this, data) - } - - setTitle(title: string): this { - this.title = title - return this - } - - setIcon(iconURL: string): this { - this.icon_url = iconURL - return this - } - - setColor(color: string): this { - this.color = color - return this - } - - setDescription(description: string): this { - this.description = description - return this - } - - setURL(url: string): this { - this.url = url - return this - } - - toJSON(): unknown { - return { - title: this.title, - type: this.type, - description: this.description, - url: this.url - } - } + type: Embed['type'] = 'Website'; + url?: string; + special?: EmbedSpecial; + title?: string; + description?: string; + image?: EmbedImage; + video?: EmbedVideo; + site_name?: string; + icon_url?: string; + color?: string; + + constructor(data: Partial = {}) { + Object.assign(this, data); + } + + setTitle(title: string): this { + this.title = title; + return this; + } + + setIcon(iconURL: string): this { + this.icon_url = iconURL; + return this; + } + + setColor(color: string): this { + this.color = color; + return this; + } + + setDescription(description: string): this { + this.description = description; + return this; + } + + setURL(url: string): this { + this.url = url; + return this; + } + + toJSON(): unknown { + return { + title: this.title, + type: this.type, + description: this.description, + url: this.url, + }; + } } diff --git a/src/structures/NotesChannel.ts b/src/structures/NotesChannel.ts index ec40534..f7dbe47 100644 --- a/src/structures/NotesChannel.ts +++ b/src/structures/NotesChannel.ts @@ -1,42 +1,43 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { User, Channel, Message } from './index' -import { TextBasedChannel } from './interfaces/index' -import { Client } from '../client/Client' -import { MessageManager, MessageOptions } from '../managers/index' -import { ChannelTypes } from '../util/index' - -type APINotesChannel = Extract - -export class NotesChannel extends Channel implements TextBasedChannel { - readonly type = ChannelTypes.NOTES - userId!: string - lastMessageId: string | null = null - messages = new MessageManager(this) - constructor(client: Client, data: APINotesChannel) { - super(client, data) - this._patch(data) +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Channel, Message, User } from './mod.ts'; +import { TextBasedChannel } from './interfaces/mod.ts'; +import { Client } from '../client/Client.ts'; +import { MessageManager, MessageOptions } from '../managers/mod.ts'; +import { ChannelTypes } from '../util/mod.ts'; + +type APINotesChannel = Extract; + +export class NotesChannel extends Channel + implements TextBasedChannel { + readonly type = ChannelTypes.NOTES; + userId!: string; + lastMessageId: string | null = null; + messages = new MessageManager(this); + constructor(client: Client, data: APINotesChannel) { + super(client); + this._patch(data); + } + + protected _patch(data: APINotesChannel): this { + super._patch(data); + + if (data.user) { + this.userId = data.user; } - protected _patch(data: APINotesChannel): this { - super._patch(data) + return this; + } - if (data.user) { - this.userId = data.user - } + send(options: MessageOptions | string): Promise { + return this.messages.send(options); + } - return this - } - - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } + get lastMessage(): Message | null { + if (!this.lastMessageId) return null; + return this.messages.cache.get(this.lastMessageId) ?? null; + } - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } - - get user(): User { - return this.client.user! - } + get user(): User { + return this.client.user!; + } } diff --git a/src/structures/Role.ts b/src/structures/Role.ts index 048249f..65a852f 100644 --- a/src/structures/Role.ts +++ b/src/structures/Role.ts @@ -1,50 +1,53 @@ -import type { Role as APIRole } from 'revolt-api' -import { Base, Server, Overwrite } from './index' -import { UUID, ChannelPermissions } from '../util/index' +import type { Role as APIRole } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Base, Overwrite, Server } from './mod.ts'; +import { ChannelPermissions, UUID } from '../util/mod.ts'; export class Role extends Base { - name!: string - color: string | null = null - hoist = false - rank!: number - overwrite!: Overwrite - constructor(public server: Server, data: APIRole & { id: string }) { - super(server.client) - this._patch(data) + name!: string; + color: string | null = null; + hoist = false; + rank!: number; + overwrite!: Overwrite; + constructor(public server: Server, data: APIRole & { id: string }) { + super(server.client); + this._patch(data); + } + + protected _patch(data: APIRole & { _id?: string }): this { + super._patch(data); + + if (data.name) this.name = data.name; + if (typeof data.hoist === 'boolean') this.hoist = data.hoist; + if (typeof data.rank === 'number') this.rank = data.rank; + if ('colour' in data) this.color = data.colour ?? null; + if (data.permissions) { + const { a, d } = data.permissions; + this.overwrite = { + allow: new ChannelPermissions(a), + deny: new ChannelPermissions(d), + }; } - protected _patch(data: APIRole & { _id?: string }): this { - super._patch(data) + return this; + } - if (data.name) this.name = data.name - if (typeof data.hoist === 'boolean') this.hoist = data.hoist - if (typeof data.rank === 'number') this.rank = data.rank - if ('colour' in data) this.color = data.colour ?? null - if (data.permissions) { - const { a, d } = data.permissions - this.overwrite = { allow: new ChannelPermissions(a), deny: new ChannelPermissions(d) } - } + get createdAt(): Date { + return UUID.timestampOf(this.id); + } - return this - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() - } + get createdTimestamp(): number { + return this.createdAt.getTime(); + } - get permissions(): Overwrite { - return this.overwrite - } + get permissions(): Overwrite { + return this.overwrite; + } - async delete(): Promise { - await this.server.roles.delete(this) - } + async delete(): Promise { + await this.server.roles.delete(this); + } - toString(): string { - return `<@&${this.id}>` - } + toString(): string { + return `<@&${this.id}>`; + } } diff --git a/src/structures/Server.ts b/src/structures/Server.ts index 4bcc317..68c9032 100644 --- a/src/structures/Server.ts +++ b/src/structures/Server.ts @@ -1,117 +1,128 @@ -import type { Server as APIServer } from 'revolt-api' -import { Base, ServerMember, User, Category } from './index' -import { Client } from '../client/Client' -import { RoleManager, ServerChannelManager, ServerMemberManager } from '../managers/index' -import { Collection, ServerPermissions, UUID } from '../util/index' +import type { Server as APIServer } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Base, Category, ServerMember, User } from './mod.ts'; +import { Client } from '../client/Client.ts'; +import { + RoleManager, + ServerChannelManager, + ServerMemberManager, +} from '../managers/mod.ts'; +import { Collection, ServerPermissions, UUID } from '../util/mod.ts'; export class Server extends Base { - name!: string - description: string | null = null - ownerId!: string - members = new ServerMemberManager(this) - channels = new ServerChannelManager(this) - roles = new RoleManager(this) - icon: string | null = null - banner: string | null = null - analytics = false - discoverable = false - nsfw = false - permissions!: ServerPermissions - categories = new Collection() - - constructor(client: Client, data: APIServer) { - super(client) - this._patch(data) + name!: string; + description: string | null = null; + ownerId!: string; + members = new ServerMemberManager(this); + channels = new ServerChannelManager(this); + roles = new RoleManager(this); + icon: string | null = null; + banner: string | null = null; + analytics = false; + discoverable = false; + nsfw = false; + permissions!: ServerPermissions; + categories = new Collection(); + + constructor(client: Client, data: APIServer) { + super(client); + this._patch(data); + } + + protected _patch(data: APIServer): this { + super._patch(data); + + if (Array.isArray(data.categories)) { + this.categories.clear(); + for (const cat of data.categories) { + const category = new Category(this, cat); + this.categories.set(category.id, category); + } } - protected _patch(data: APIServer): this { - super._patch(data) - - if (Array.isArray(data.categories)) { - this.categories.clear() - for (const cat of data.categories) { - const category = new Category(this, cat) - this.categories.set(category.id, category) - } - } - - if ('icon' in data) { - this.icon = data.icon?._id ?? null - } - - if ('banner' in data) { - this.banner = data.banner?._id ?? null - } - - if (data.owner) { - this.ownerId = data.owner - } - - if (data.name) { - this.name = data.name - } - - if ('description' in data) { - this.description = data.description ?? null - } - - if (Array.isArray(data.channels)) { - for (const id of data.channels) { - const channel = this.client.channels.cache.get(id) - if (channel?.inServer()) this.channels.cache.set(channel.id, channel) - } - } - - if (typeof data.roles === 'object') { - for (const [id, raw] of Object.entries(data.roles)) { - this.roles._add(Object.assign(raw, { id })) - } - } - - if (typeof data.default_permissions === 'number') { - this.permissions = new ServerPermissions(data.default_permissions).freeze() - } - - if (typeof data.analytics === 'boolean') this.analytics = data.analytics - if (typeof data.discoverable === 'boolean') this.discoverable = data.discoverable - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - - return this + if ('icon' in data) { + this.icon = data.icon?._id ?? null; } - async ack(): Promise { - await this.client.servers.ack(this) + if ('banner' in data) { + this.banner = data.banner?._id ?? null; } - async delete(): Promise { - await this.client.servers.delete(this) + if (data.owner) { + this.ownerId = data.owner; } - iconURL(options?: { size: number }): string | null { - return this.icon ? this.client.endpoints.icon(this.icon, options?.size) : null + if (data.name) { + this.name = data.name; } - bannerURL(options?: { size: number }): string | null { - return this.banner ? this.client.endpoints.banner(this.banner, options?.size) : null + if ('description' in data) { + this.description = data.description ?? null; } - get me(): ServerMember | null { - return this.members.cache.get(this.client.user?.id as string) ?? null + if (Array.isArray(data.channels)) { + for (const id of data.channels) { + const channel = this.client.channels.cache.get(id); + if (channel?.inServer()) this.channels.cache.set(channel.id, channel); + } } - get createdAt(): Date { - return UUID.timestampOf(this.id) + if (typeof data.roles === 'object') { + for (const [id, raw] of Object.entries(data.roles)) { + this.roles._add(Object.assign(raw, { id })); + } } - get createdTimestamp(): number { - return this.createdAt.getTime() + if (typeof data.default_permissions === 'number') { + this.permissions = new ServerPermissions(data.default_permissions) + .freeze(); } - get owner(): User | null { - return this.client.users.cache.get(this.ownerId) ?? null - } - - toString(): string { - return this.name + if (typeof data.analytics === 'boolean') this.analytics = data.analytics; + if (typeof data.discoverable === 'boolean') { + this.discoverable = data.discoverable; } + if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw; + + return this; + } + + async ack(): Promise { + await this.client.servers.ack(this); + } + + async delete(): Promise { + await this.client.servers.delete(this); + } + + iconURL(options?: { size: number }): string | null { + return this.icon + ? this.client.api.cdn.icon(this.icon, options?.size) + : null; + } + + bannerURL(options?: { size: number }): string | null { + return this.banner + ? this.client.api.cdn.banner(this.banner, options?.size) + : null; + } + + get me(): ServerMember | null { + return this.members.cache.get(this.client.user?.id as string) ?? null; + } + + get createdAt(): Date { + return UUID.timestampOf(this.id); + } + + get createdTimestamp(): number { + return this.createdAt.getTime(); + } + + get owner(): User | null { + return this.client.users.cache.get(this.ownerId) ?? null; + } + + toString(): string { + return this.name; + } } diff --git a/src/structures/ServerChannel.ts b/src/structures/ServerChannel.ts index b2e7db4..e408795 100644 --- a/src/structures/ServerChannel.ts +++ b/src/structures/ServerChannel.ts @@ -1,59 +1,69 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Category, Channel, Server } from './index' -import { Client } from '../client/Client' -import { ChannelPermissions, Collection } from '../util/index' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Category, Channel, Server } from './mod.ts'; +import { Client } from '../client/Client.ts'; +import { ChannelPermissions, Collection } from '../util/mod.ts'; -type APIServerChannel = Extract +type APIServerChannel = Extract< + APIChannel, + { channel_type: 'TextChannel' | 'VoiceChannel' } +>; export interface Overwrite { - allow: ChannelPermissions - deny: ChannelPermissions + allow: ChannelPermissions; + deny: ChannelPermissions; } -export class ServerChannel extends Channel { - name!: string - serverId!: string - description: string | null = null - icon: string | null = null - overwrites = new Collection() - nsfw = false - constructor(client: Client, data: T) { - super(client, data) - this._patch(data) - } +export class ServerChannel + extends Channel { + name!: string; + serverId!: string; + description: string | null = null; + icon: string | null = null; + overwrites = new Collection(); + nsfw = false; + constructor(client: Client, data: T) { + super(client); + this._patch(data); + } - protected _patch(data: T): this { - super._patch(data) - - if (data.name) this.name = data.name - if (data.server) this.serverId = data.server - if ('description' in data) this.description = data.description ?? null - if ('icon' in data) this.icon = data.icon?._id ?? null - if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw - if (data.role_permissions) { - this.overwrites.clear() - for (const [id, { a, d }] of Object.entries(data.role_permissions)) { - this.overwrites.set(id, { allow: new ChannelPermissions(a), deny: new ChannelPermissions(d) }) - } - } - - return this - } + protected _patch(data: T): this { + super._patch(data); - async createInvite(): Promise { - const invite = await this.client.api.post(`/channels/${this.id}/invites`) - return this.client.endpoints.invite(invite._id) + if (data.name) this.name = data.name; + if (data.server) this.serverId = data.server; + if ('description' in data) this.description = data.description ?? null; + if ('icon' in data) this.icon = data.icon?._id ?? null; + if (typeof data.nsfw === 'boolean') this.nsfw = data.nsfw; + if (data.role_permissions) { + this.overwrites.clear(); + for (const [id, { a, d }] of Object.entries(data.role_permissions)) { + this.overwrites.set(id, { + allow: new ChannelPermissions(a), + deny: new ChannelPermissions(d), + }); + } } - iconURL(options?: { size: number }): string | null { - return this.icon ? this.client.endpoints.icon(this.icon, options?.size) : null - } + return this; + } - get server(): Server { - return this.client.servers.cache.get(this.serverId) as Server - } + async createInvite(): Promise { + const invite = await this.client.api.post(`/channels/${this.id}/invites`); + return this.client.api.cdn.invite(invite._id); + } - get category(): Category | null { - return this.server.categories.find(cat => cat.children.has(this.id)) ?? null - } + iconURL(options?: { size: number }): string | null { + return this.icon + ? this.client.api.cdn.icon(this.icon, options?.size) + : null; + } + + get server(): Server { + return this.client.servers.cache.get(this.serverId) as Server; + } + + get category(): Category | null { + return this.server.categories.find((cat) => cat.children.has(this.id)) ?? + null; + } } diff --git a/src/structures/ServerMember.ts b/src/structures/ServerMember.ts index d0057db..1e74fe3 100644 --- a/src/structures/ServerMember.ts +++ b/src/structures/ServerMember.ts @@ -1,65 +1,68 @@ -import type { Member as APIMember, File } from 'revolt-api' -import { Base, Server, User } from './index' -import { Client } from '../client/Client' +import type { + File, + Member as APIMember, +} from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Base, Server, User } from './mod.ts'; +import { Client } from '../client/Client.ts'; export class ServerMember extends Base { - serverId!: string - nickname: string | null = null - avatar: File | null = null - constructor(client: Client, data: APIMember) { - super(client) - this._patch(data) - } - - protected _patch(data: APIMember): this { - super._patch(data) - - if ('nickname' in data) { - this.nickname = data.nickname ?? null - } - - if ('avatar' in data) { - this.avatar = data.avatar ?? null - } + serverId!: string; + nickname: string | null = null; + avatar: File | null = null; + constructor(client: Client, data: APIMember) { + super(client); + this._patch(data); + } - if (data._id) { - this.serverId = data._id.server - this.id = data._id.user - } + protected _patch(data: APIMember): this { + super._patch(data); - return this + if ('nickname' in data) { + this.nickname = data.nickname ?? null; } - async setNickname(nickname?: string): Promise { - await this.server.members.edit(this, { nickname }) - return this + if ('avatar' in data) { + this.avatar = data.avatar ?? null; } - ban(reason?: string): Promise { - return this.server.members.ban(this, reason) + if (data._id) { + this.serverId = data._id.server; + this.id = data._id.user; } - kick(): Promise { - return this.server.members.kick(this) - } + return this; + } - leave(): Promise { - return this.client.servers.delete(this.serverId) - } + async setNickname(nickname?: string): Promise { + await this.server.members.edit(this, { nickname }); + return this; + } - displayAvatarURL(options?: { size: number }): string { - return this.user.displayAvatarURL(options) - } + ban(reason?: string): Promise { + return this.server.members.ban(this, reason); + } - get user(): User { - return this.client.users.cache.get(this.id)! - } + kick(): Promise { + return this.server.members.kick(this); + } - get server(): Server { - return this.client.servers.cache.get(this.serverId)! - } + leave(): Promise { + return this.client.servers.delete(this.serverId); + } - toString(): string { - return `<@${this.id}>` - } + displayAvatarURL(options?: { size: number }): string { + return this.user.displayAvatarURL(options); + } + + get user(): User { + return this.client.users.cache.get(this.id)!; + } + + get server(): Server { + return this.client.servers.cache.get(this.serverId)!; + } + + toString(): string { + return `<@${this.id}>`; + } } diff --git a/src/structures/TextChannel.ts b/src/structures/TextChannel.ts index 778a34b..176addc 100644 --- a/src/structures/TextChannel.ts +++ b/src/structures/TextChannel.ts @@ -1,35 +1,36 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { Message, ServerChannel } from './index' -import { TextBasedChannel } from './interfaces/index' -import { Client } from '../client/Client' -import { MessageManager, MessageOptions } from '../managers/index' -import { ChannelTypes } from '../util/index' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Message, ServerChannel } from './mod.ts'; +import { TextBasedChannel } from './interfaces/mod.ts'; +import { Client } from '../client/Client.ts'; +import { MessageManager, MessageOptions } from '../managers/mod.ts'; +import { ChannelTypes } from '../util/mod.ts'; -type APITextChannel = Extract +type APITextChannel = Extract; -export class TextChannel extends ServerChannel implements TextBasedChannel { - lastMessageId: string | null = null - messages = new MessageManager(this) - readonly type = ChannelTypes.TEXT - constructor(client: Client, data: APITextChannel) { - super(client, data) - this._patch(data) - } +export class TextChannel extends ServerChannel + implements TextBasedChannel { + lastMessageId: string | null = null; + messages = new MessageManager(this); + readonly type = ChannelTypes.TEXT; + constructor(client: Client, data: APITextChannel) { + super(client, data); + this._patch(data); + } - protected _patch(data: APITextChannel): this { - super._patch(data) + protected _patch(data: APITextChannel): this { + super._patch(data); - if (data.last_message_id) this.lastMessageId = data.last_message_id + if (data.last_message_id) this.lastMessageId = data.last_message_id; - return this - } + return this; + } - send(options: MessageOptions | string): Promise { - return this.messages.send(options) - } + send(options: MessageOptions | string): Promise { + return this.messages.send(options); + } - get lastMessage(): Message | null { - if (!this.lastMessageId) return null - return this.messages.cache.get(this.lastMessageId) ?? null - } + get lastMessage(): Message | null { + if (!this.lastMessageId) return null; + return this.messages.cache.get(this.lastMessageId) ?? null; + } } diff --git a/src/structures/User.ts b/src/structures/User.ts index 4f881da..d8b5a64 100644 --- a/src/structures/User.ts +++ b/src/structures/User.ts @@ -1,88 +1,101 @@ -import type { User as APIUser, Presence as APIPresence, File } from 'revolt-api' -import { Base, DMChannel } from './index' -import { Client } from '../client/Client' -import { Badges, Presence, UUID } from '../util/index' +import type { + File, + Presence as APIPresence, + User as APIUser, +} from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { Base, DMChannel } from './mod.ts'; +import { Client } from '../client/Client.ts'; +import { Badges, Presence, UUID } from '../util/mod.ts'; export class User extends Base { - username!: string - avatar: File | null = null - status = { - text: null, - presence: Presence.INVISIBLE - } as { - text: string | null - presence: Presence + username!: string; + avatar: File | null = null; + status = { + text: null, + presence: Presence.INVISIBLE, + } as { + text: string | null; + presence: Presence; + }; + badges!: Badges; + bot = false; + + constructor(client: Client, data: APIUser) { + super(client); + this._patch(data); + } + + protected _patch(data: APIUser): this { + super._patch(data); + + if (data.username) { + this.username = data.username; } - badges!: Badges - bot = false - constructor(client: Client, data: APIUser) { - super(client) - this._patch(data) + if (data.bot) { + this.bot = true; } - protected _patch(data: APIUser): this { - super._patch(data) - - if (data.username) { - this.username = data.username - } - - if (data.bot) { - this.bot = true - } - - if (typeof data.badges === 'number') { - this.badges = new Badges(data.badges).freeze() - } - - if ('avatar' in data) { - this.avatar = data.avatar ?? null - } - - if ('status' in data) { - const presence = data.status?.presence ? Presence[data.status.presence.toUpperCase() as Uppercase] : Presence.INVISIBLE - this.status.presence = presence - this.status.text = data.status?.text ?? null - } - - return this - } - - get createdAt(): Date { - return UUID.timestampOf(this.id) - } - - get createdTimestamp(): number { - return this.createdAt.getTime() + if (typeof data.badges === 'number') { + this.badges = new Badges(data.badges).freeze(); } - async block(): Promise { - await this.client.api.put(`/users/${this.id}/block`) + if ('avatar' in data) { + this.avatar = data.avatar ?? null; } - async unblock(): Promise { - await this.client.api.delete(`/users/${this.id}/block`) + if ('status' in data) { + const presence = data.status?.presence + ? Presence[data.status.presence.toUpperCase() as Uppercase] + : Presence.INVISIBLE; + this.status.presence = presence; + this.status.text = data.status?.text ?? null; } - async createDM(): Promise { - const data = await this.client.api.get(`/users/${this.id}/dm`) - return this.client.channels._add(data) as DMChannel - } - - avatarURL(options?: { size: number }): string | null { - return this.avatar ? this.client.endpoints.avatar(this.avatar._id, this.avatar.filename, options?.size) : null - } - - displayAvatarURL(options?: { size: number }): string { - return this.avatarURL(options) ?? this.client.endpoints.defaultAvatar(this.id) - } - - fetch(force = true): Promise { - return this.client.users.fetch(this, { force }) - } - - toString(): string { - return `<@${this.id}>` - } + return this; + } + + get createdAt(): Date { + return UUID.timestampOf(this.id); + } + + get createdTimestamp(): number { + return this.createdAt.getTime(); + } + + async block(): Promise { + await this.client.api.put(`/users/${this.id}/block`); + } + + async unblock(): Promise { + await this.client.api.delete(`/users/${this.id}/block`); + } + + async createDM(): Promise { + const data = await this.client.api.get(`/users/${this.id}/dm`); + return this.client.channels._add(data) as DMChannel; + } + + avatarURL(options?: { size: number }): string | null { + return this.avatar + ? this.client.api.cdn.avatar( + this.avatar._id, + this.avatar.filename, + options?.size, + ) + : null; + } + + displayAvatarURL(options?: { size: number }): string { + return this.avatarURL(options) ?? + this.client.api.cdn.defaultAvatar(this.id); + } + + fetch(force = true): Promise { + return this.client.users.fetch(this, { force }); + } + + toString(): string { + return `<@${this.id}>`; + } } diff --git a/src/structures/VoiceChannel.ts b/src/structures/VoiceChannel.ts index 7e4cb33..6c5ab2f 100644 --- a/src/structures/VoiceChannel.ts +++ b/src/structures/VoiceChannel.ts @@ -1,23 +1,23 @@ -import type { Channel as APIChannel } from 'revolt-api' -import { ServerChannel } from './index' -import { Client } from '../index' -import { ChannelTypes } from '../util/index' +import type { Channel as APIChannel } from 'https://deno.land/x/revolt_api@0.4.0/types.ts'; +import { ServerChannel } from './mod.ts'; +import { Client } from '../lib.ts'; +import { ChannelTypes } from '../util/mod.ts'; -type APIVoiceChannel = Extract +type APIVoiceChannel = Extract; export class VoiceChannel extends ServerChannel { - readonly type = ChannelTypes.VOICE - constructor(client: Client, data: APIVoiceChannel) { - super(client, data) - this._patch(data) - } + readonly type = ChannelTypes.VOICE; + constructor(client: Client, data: APIVoiceChannel) { + super(client, data); + this._patch(data); + } - protected _patch(data: APIVoiceChannel): this { - super._patch(data) - return this - } + protected _patch(data: APIVoiceChannel): this { + super._patch(data); + return this; + } - async ack(): Promise { - throw new TypeError('Cannot ack voice channel') - } + ack(): Promise { + throw new TypeError('Cannot ack voice channel'); + } } diff --git a/src/structures/index.ts b/src/structures/index.ts deleted file mode 100644 index cf60381..0000000 --- a/src/structures/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export * from './Base' -export * from './Category' -export * from './Channel' -export * from './ClientUser' -export * from './DMChannel' -export * from './GroupChannel' -export * from './Mentions' -export * from './Message' -export * from './NotesChannel' -export * from './Role' -export * from './Server' -export * from './ServerChannel' -export * from './ServerMember' -export * from './TextChannel' -export * from './User' -export * from './VoiceChannel' diff --git a/src/structures/interfaces/TextBasedChannel.ts b/src/structures/interfaces/TextBasedChannel.ts index d4db558..d729c78 100644 --- a/src/structures/interfaces/TextBasedChannel.ts +++ b/src/structures/interfaces/TextBasedChannel.ts @@ -1,8 +1,8 @@ -import type { MessageManager, Message, MessageOptions } from '../../index' +import type { Message, MessageManager, MessageOptions } from '../../lib.ts'; export interface TextBasedChannel { - messages: MessageManager - lastMessageId: string | null - lastMessage: Message | null - send(options: MessageOptions | string): Promise + messages: MessageManager; + lastMessageId: string | null; + lastMessage: Message | null; + send(options: MessageOptions | string): Promise; } diff --git a/src/structures/interfaces/index.ts b/src/structures/interfaces/index.ts deleted file mode 100644 index 7fecce7..0000000 --- a/src/structures/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TextBasedChannel' diff --git a/src/structures/interfaces/mod.ts b/src/structures/interfaces/mod.ts new file mode 100644 index 0000000..71409ce --- /dev/null +++ b/src/structures/interfaces/mod.ts @@ -0,0 +1 @@ +export * from './TextBasedChannel.ts'; diff --git a/src/structures/mod.ts b/src/structures/mod.ts new file mode 100644 index 0000000..6131131 --- /dev/null +++ b/src/structures/mod.ts @@ -0,0 +1,16 @@ +export * from './Base.ts'; +export * from './Category.ts'; +export * from './Channel.ts'; +export * from './ClientUser.ts'; +export * from './DMChannel.ts'; +export * from './GroupChannel.ts'; +export * from './Mentions.ts'; +export * from './Message.ts'; +export * from './NotesChannel.ts'; +export * from './Role.ts'; +export * from './Server.ts'; +export * from './ServerChannel.ts'; +export * from './ServerMember.ts'; +export * from './TextChannel.ts'; +export * from './User.ts'; +export * from './VoiceChannel.ts'; diff --git a/src/util/Badges.ts b/src/util/Badges.ts index 95ebd10..e924b3f 100644 --- a/src/util/Badges.ts +++ b/src/util/Badges.ts @@ -1,33 +1,33 @@ -import { BitField } from './BitField' +import { BitField } from './BitField.ts'; -export type BadgeString = keyof typeof FLAGS -export type BadgesResolvable = number | BadgeString | BadgesResolvable[] +export type BadgeString = keyof typeof FLAGS; +export type BadgesResolvable = number | BadgeString | BadgesResolvable[]; export declare interface Badges { - serialize(): Record - any(bit: BadgesResolvable): boolean - add(...bits: BadgesResolvable[]): this - remove(...bits: BadgesResolvable[]): this - has(bit: BadgesResolvable): boolean + serialize(): Record; + any(bit: BadgesResolvable): boolean; + add(...bits: BadgesResolvable[]): this; + remove(...bits: BadgesResolvable[]): this; + has(bit: BadgesResolvable): boolean; } const FLAGS = { - DEVELOPER: 1 << 0, - TRANSLATOR: 1 << 1, - SUPPORTER: 1 << 2, - RESPONSIBLE_DISCLOSURE: 1 << 3, - REVOLT_TEAM: 1 << 4, - EARLY_ADOPTER: 1 << 8 -} as const + DEVELOPER: 1 << 0, + TRANSLATOR: 1 << 1, + SUPPORTER: 1 << 2, + RESPONSIBLE_DISCLOSURE: 1 << 3, + REVOLT_TEAM: 1 << 4, + EARLY_ADOPTER: 1 << 8, +} as const; export class Badges extends BitField { - static FLAGS: typeof FLAGS - constructor(bits?: BadgesResolvable) { - super(bits) - } - static resolve(bit: BadgesResolvable): number { - return super.resolve(bit) - } + static FLAGS: typeof FLAGS; + constructor(bits?: BadgesResolvable) { + super(bits); + } + static resolve(bit: BadgesResolvable): number { + return super.resolve(bit); + } } -Badges.FLAGS = FLAGS +Badges.FLAGS = FLAGS; diff --git a/src/util/BitField.ts b/src/util/BitField.ts index 44ee9ac..4330bca 100644 --- a/src/util/BitField.ts +++ b/src/util/BitField.ts @@ -1,92 +1,107 @@ -import { RangeError } from '../errors/index' +import { RangeError } from '../errors/mod.ts'; -const DEFAULT_BIT = 0 +const DEFAULT_BIT = 0; -export type BitFieldResolvable = BitField | number | string | BitFieldResolvable[] +export type BitFieldResolvable = + | BitField + | number + | string + | BitFieldResolvable[]; export class BitField { - static FLAGS: Record = {} - bitfield = DEFAULT_BIT - constructor(bits: BitFieldResolvable = DEFAULT_BIT) { - this.bitfield = this.self.resolve(bits) + static FLAGS: Record = {}; + bitfield = DEFAULT_BIT; + constructor(bits: BitFieldResolvable = DEFAULT_BIT) { + this.bitfield = this.self.resolve(bits); + } + + static resolve(bit: BitFieldResolvable): number { + if (bit instanceof BitField) return bit.bitfield; + if (typeof bit === 'number' && bit >= DEFAULT_BIT) return bit; + if (Array.isArray(bit)) { + return bit.map((p) => this.resolve(p)).reduce( + (prev, p) => prev | p, + DEFAULT_BIT, + ); } - - static resolve(bit: BitFieldResolvable): number { - if (bit instanceof BitField) return bit.bitfield - if (typeof bit === 'number' && bit >= DEFAULT_BIT) return bit - if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, DEFAULT_BIT) - if (typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit] - throw new RangeError('BITFIELD_INVALID', bit) - } - get self(): { - FLAGS: Record - resolve(bit: BitFieldResolvable): number - new (bits?: BitFieldResolvable): BitField - } { - return this.constructor as unknown as { - FLAGS: Record - resolve(bit: BitFieldResolvable): number - new (bits?: BitFieldResolvable): BitField - } - } - - any(bit: BitFieldResolvable): boolean { - bit = this.self.resolve(bit) - return (this.bitfield & bit) !== DEFAULT_BIT + if (typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit]; + throw new RangeError('BITFIELD_INVALID', bit); + } + get self(): { + FLAGS: Record; + resolve(bit: BitFieldResolvable): number; + new (bits?: BitFieldResolvable): BitField; + } { + return this.constructor as unknown as { + FLAGS: Record; + resolve(bit: BitFieldResolvable): number; + new (bits?: BitFieldResolvable): BitField; + }; + } + + any(bit: BitFieldResolvable): boolean { + bit = this.self.resolve(bit); + return (this.bitfield & bit) !== DEFAULT_BIT; + } + + has(bit: BitFieldResolvable): boolean { + bit = this.self.resolve(bit); + return (this.bitfield & bit) === bit; + } + + toArray(): string[] { + return Object.keys(this.self.FLAGS).filter((bit) => this.has(bit)); + } + + add(...bits: BitFieldResolvable[]): this { + let total = 0; + + for (const bit of bits) { + total |= this.self.resolve(bit); } - has(bit: BitFieldResolvable): boolean { - bit = this.self.resolve(bit) - return (this.bitfield & bit) === bit + if (Object.isFrozen(this)) { + return new this.self(this.bitfield | total) as this; } - toArray(): string[] { - return Object.keys(this.self.FLAGS).filter(bit => this.has(bit)) - } - - add(...bits: BitFieldResolvable[]): this { - let total = 0 - - for (const bit of bits) { - total |= this.self.resolve(bit) - } + this.bitfield |= total; - if (Object.isFrozen(this)) return new this.self(this.bitfield | total) as this + return this; + } - this.bitfield |= total + remove(...bits: BitFieldResolvable[]): this { + let total = 0; - return this + for (const bit of bits) { + total |= this.self.resolve(bit); } - remove(...bits: BitFieldResolvable[]): this { - let total = 0 - - for (const bit of bits) { - total |= this.self.resolve(bit) - } + if (Object.isFrozen(this)) { + return new this.self(this.bitfield & ~total) as this; + } - if (Object.isFrozen(this)) return new this.self(this.bitfield & ~total) as this + this.bitfield &= ~total; - this.bitfield &= ~total + return this; + } - return this - } + freeze(): Readonly { + return Object.freeze(this); + } - freeze(): Readonly { - return Object.freeze(this) - } + valueOf(): number { + return this.bitfield; + } - valueOf(): number { - return this.bitfield + serialize(): Record { + const serialized: Record = {}; + for (const [flag, bit] of Object.entries(this.self.FLAGS)) { + serialized[flag] = this.has(bit); } + return serialized; + } - serialize(): Record { - const serialized: Record = {} - for (const [flag, bit] of Object.entries(this.self.FLAGS)) serialized[flag] = this.has(bit) - return serialized - } - - *[Symbol.iterator](): Iterable { - yield* this.toArray() - } + *[Symbol.iterator](): Iterable { + yield* this.toArray(); + } } diff --git a/src/util/Collection.ts b/src/util/Collection.ts index 9729d03..864ea77 100644 --- a/src/util/Collection.ts +++ b/src/util/Collection.ts @@ -1 +1 @@ -export { Collection } from '@discordjs/collection' +export { Collection } from 'https://esm.sh/@discordjs/collection@0.6.0'; diff --git a/src/util/Constants.ts b/src/util/Constants.ts index 0e40d32..e58ecf2 100644 --- a/src/util/Constants.ts +++ b/src/util/Constants.ts @@ -1,92 +1,90 @@ -import { UUID } from './UUID' -import { BaseClientOptions } from '../client/BaseClient' +import { UUID } from './UUID.ts'; +import { BaseClientOptions } from '../client/BaseClient.ts'; export enum Events { - DEBUG = 'debug', - ERROR = 'error', - RAW = 'raw', - MESSAGE = 'message', - READY = 'ready', - CHANNEL_CREATE = 'channelCreate', - CHANNEL_DELETE = 'channelDelete', - SERVER_DELETE = 'serverDelete', - SERVER_UPDATE = 'serverUpdate', - SERVER_CREATE = 'serverCreate', - MESSAGE_DELETE = 'messageDelete', - MESSAGE_UPDATE = 'messageUpdate', - USER_UPDATE = 'userUpdate', - SERVER_MEMBER_JOIN = 'serverMemberJoin', - CHANNEL_UPDATE = 'channelUpdate', - SERVER_MEMBER_LEAVE = 'serverMemberLeave', - SERVER_MEMBER_UPDATE = 'serverMemberUpdate', - ROLE_CREATE = 'roleCreate', - ROLE_DELETE = 'roleDelete', - TYPING_START = 'typingStart', - TYPING_STOP = 'typingStop', - GROUP_JOIN = 'groupJoin', - GROUP_LEAVE = 'groupLeave' + DEBUG = 'debug', + ERROR = 'error', + RAW = 'raw', + MESSAGE = 'message', + READY = 'ready', + CHANNEL_CREATE = 'channelCreate', + CHANNEL_DELETE = 'channelDelete', + SERVER_DELETE = 'serverDelete', + SERVER_UPDATE = 'serverUpdate', + SERVER_CREATE = 'serverCreate', + MESSAGE_DELETE = 'messageDelete', + MESSAGE_UPDATE = 'messageUpdate', + USER_UPDATE = 'userUpdate', + SERVER_MEMBER_JOIN = 'serverMemberJoin', + CHANNEL_UPDATE = 'channelUpdate', + SERVER_MEMBER_LEAVE = 'serverMemberLeave', + SERVER_MEMBER_UPDATE = 'serverMemberUpdate', + ROLE_CREATE = 'roleCreate', + ROLE_DELETE = 'roleDelete', + TYPING_START = 'typingStart', + TYPING_STOP = 'typingStop', + GROUP_JOIN = 'groupJoin', + GROUP_LEAVE = 'groupLeave', } export enum WSEvents { - AUTHENTICATE = 'Authenticate', - AUTHENTICATED = 'Authenticated', - BEGIN_TYPING = 'BeginTyping', - CHANNEL_ACK = 'ChannelAck', - CHANNEL_CREATE = 'ChannelCreate', - CHANNEL_DELETE = 'ChannelDelete', - CHANNEL_GROUP_JOIN = 'ChannelGroupJoin', - CHANNEL_GROUP_LEAVE = 'ChannelGroupLeave', - CHANNEL_START_TYPING = 'ChannelStartTyping', - CHANNEL_STOP_TYPING = 'ChannelStopTyping', - CHANNEL_UPDATE = 'ChannelUpdate', - END_TYPING = 'EndTyping', - ERROR = 'Error', - MESSAGE = 'Message', - MESSAGE_DELETE = 'MessageDelete', - MESSAGE_UPDATE = 'MessageUpdate', - PING = 'Ping', - PONG = 'Pong', - READY = 'Ready', - SERVER_DELETE = 'ServerDelete', - SERVER_MEMBER_JOIN = 'ServerMemberJoin', - SERVER_MEMBER_LEAVE = 'ServerMemberLeave', - SERVER_MEMBER_UPDATE = 'ServerMemberUpdate', - SERVER_ROLE_DELETE = 'ServerRoleDelete', - SERVER_ROLE_UPDATE = 'ServerRoleUpdate', - SERVER_UPDATE = 'ServerUpdate', - USER_RELATIONSHIP = 'UserRelationship', - USER_UPDATE = 'UserUpdate' + AUTHENTICATE = 'Authenticate', + AUTHENTICATED = 'Authenticated', + BEGIN_TYPING = 'BeginTyping', + BULK = 'Bulk', + CHANNEL_ACK = 'ChannelAck', + CHANNEL_CREATE = 'ChannelCreate', + CHANNEL_DELETE = 'ChannelDelete', + CHANNEL_GROUP_JOIN = 'ChannelGroupJoin', + CHANNEL_GROUP_LEAVE = 'ChannelGroupLeave', + CHANNEL_START_TYPING = 'ChannelStartTyping', + CHANNEL_STOP_TYPING = 'ChannelStopTyping', + CHANNEL_UPDATE = 'ChannelUpdate', + END_TYPING = 'EndTyping', + ERROR = 'Error', + MESSAGE = 'Message', + MESSAGE_DELETE = 'MessageDelete', + MESSAGE_UPDATE = 'MessageUpdate', + PING = 'Ping', + PONG = 'Pong', + READY = 'Ready', + SERVER_DELETE = 'ServerDelete', + SERVER_MEMBER_JOIN = 'ServerMemberJoin', + SERVER_MEMBER_LEAVE = 'ServerMemberLeave', + SERVER_MEMBER_UPDATE = 'ServerMemberUpdate', + SERVER_ROLE_DELETE = 'ServerRoleDelete', + SERVER_ROLE_UPDATE = 'ServerRoleUpdate', + SERVER_UPDATE = 'ServerUpdate', + USER_RELATIONSHIP = 'UserRelationship', + USER_UPDATE = 'UserUpdate', } export enum Presence { - ONLINE = 'ONLINE', - IDLE = 'IDLE', - BUSY = 'DND', - INVISIBLE = 'OFFLINE' + ONLINE = 'ONLINE', + IDLE = 'IDLE', + BUSY = 'DND', + INVISIBLE = 'OFFLINE', } export enum ChannelTypes { - DM = 'DM', - GROUP = 'GROUP', - TEXT = 'TEXT', - VOICE = 'VOICE', - NOTES = 'NOTES' + DM = 'DM', + GROUP = 'GROUP', + TEXT = 'TEXT', + VOICE = 'VOICE', + NOTES = 'NOTES', } export const DEFAULT_CLIENT_OPTIONS: BaseClientOptions = { - rest: { - url: 'https://api.revolt.chat', - timeout: 15_000, - retries: 3 - }, - endpoints: { - api: 'https://api.revolt.chat', - cdn: 'https://autumn.revolt.chat', - invite: 'https://app.revolt.chat' - }, - ws: { - heartbeat: 3_000 - } -} as const + rest: { + api: 'https://api.revolt.chat', + app: 'https://app.revolt.chat', + cdn: 'https://autumn.revolt.chat', + timeout: 15_000, + retries: 3, + }, + ws: { + heartbeat: 3_000, + }, +} as const; -export const SYSTEM_USER_ID = '0'.repeat(UUID.TIME_LENGTH + UUID.RANDOM_LENGTH) +export const SYSTEM_USER_ID = '0'.repeat(UUID.TIME_LENGTH + UUID.RANDOM_LENGTH); diff --git a/src/util/Permissions.ts b/src/util/Permissions.ts index 02e46d1..4d28714 100644 --- a/src/util/Permissions.ts +++ b/src/util/Permissions.ts @@ -1,108 +1,120 @@ -import { BitField } from './BitField' +import { BitField } from './BitField.ts'; -export type ChannelPermissionsString = keyof typeof FLAGS['CHANNEL'] -export type UserPermissionsString = keyof typeof FLAGS['USER'] -export type ServerPermissionsString = keyof typeof FLAGS['SERVER'] -export type ChannelPermissionsResolvable = number | ChannelPermissionsString | ChannelPermissions | ChannelPermissionsResolvable[] -export type UserPermissionsResolvable = number | UserPermissionsString | UserPermissions | UserPermissionsResolvable[] -export type ServerPermissionsResolvable = number | ServerPermissionsString | ServerPermissions | ServerPermissionsResolvable[] +export type ChannelPermissionsString = keyof typeof FLAGS['CHANNEL']; +export type UserPermissionsString = keyof typeof FLAGS['USER']; +export type ServerPermissionsString = keyof typeof FLAGS['SERVER']; +export type ChannelPermissionsResolvable = + | number + | ChannelPermissionsString + | ChannelPermissions + | ChannelPermissionsResolvable[]; +export type UserPermissionsResolvable = + | number + | UserPermissionsString + | UserPermissions + | UserPermissionsResolvable[]; +export type ServerPermissionsResolvable = + | number + | ServerPermissionsString + | ServerPermissions + | ServerPermissionsResolvable[]; export declare interface ServerPermissions { - serialize(): Record - any(bit: ServerPermissionsResolvable): boolean - add(...bits: ServerPermissionsResolvable[]): this - remove(...bits: ServerPermissionsResolvable[]): this - has(bit: ServerPermissionsResolvable): boolean + serialize(): Record; + any(bit: ServerPermissionsResolvable): boolean; + add(...bits: ServerPermissionsResolvable[]): this; + remove(...bits: ServerPermissionsResolvable[]): this; + has(bit: ServerPermissionsResolvable): boolean; } export declare interface ChannelPermissions { - serialize(): Record - any(bit: ChannelPermissionsResolvable): boolean - add(...bits: ChannelPermissionsResolvable[]): this - remove(...bits: ChannelPermissionsResolvable[]): this - has(bit: ChannelPermissionsResolvable): boolean + serialize(): Record; + any(bit: ChannelPermissionsResolvable): boolean; + add(...bits: ChannelPermissionsResolvable[]): this; + remove(...bits: ChannelPermissionsResolvable[]): this; + has(bit: ChannelPermissionsResolvable): boolean; } export declare interface UserPermissions { - serialize(): Record - any(bit: UserPermissionsResolvable): boolean - add(...bits: UserPermissionsResolvable[]): this - remove(...bits: UserPermissionsResolvable[]): this - has(bit: UserPermissionsResolvable): boolean + serialize(): Record; + any(bit: UserPermissionsResolvable): boolean; + add(...bits: UserPermissionsResolvable[]): this; + remove(...bits: UserPermissionsResolvable[]): this; + has(bit: UserPermissionsResolvable): boolean; } const FLAGS = { - CHANNEL: { - VIEW_CHANNEL: 1 << 0, - SEND_MESSAGE: 1 << 1, - MANAGE_MESSAGE: 1 << 2, - MANAGE_CHANNEL: 1 << 3, - VOICE_CALL: 1 << 4, - INVITE_OTHERS: 1 << 5, - EMBED_LINKS: 1 << 6, - UPLOAD_FILES: 1 << 7 - }, - USER: { - ACCESS: 1 << 0, - VIEW_PROFILE: 1 << 1, - SEND_MESSAGES: 1 << 2, - INVITE: 1 << 3 - }, - SERVER: { - VIEW_SERVER: 1 << 0, - MANAGE_ROLES: 1 << 1, - MANAGE_CHANNELS: 1 << 2, - MANAGE_SERVER: 1 << 3, - KICK_MEMBERS: 1 << 4, - BAN_MEMBERS: 1 << 5, - CHANGE_NICKNAME: 1 << 12, - MANAGE_NICKNAMES: 1 << 13, - CHANGE_AVATAR: 1 << 14, - REMOVE_AVATARS: 1 << 15 - } -} as const + CHANNEL: { + VIEW_CHANNEL: 1 << 0, + SEND_MESSAGE: 1 << 1, + MANAGE_MESSAGE: 1 << 2, + MANAGE_CHANNEL: 1 << 3, + VOICE_CALL: 1 << 4, + INVITE_OTHERS: 1 << 5, + EMBED_LINKS: 1 << 6, + UPLOAD_FILES: 1 << 7, + }, + USER: { + ACCESS: 1 << 0, + VIEW_PROFILE: 1 << 1, + SEND_MESSAGES: 1 << 2, + INVITE: 1 << 3, + }, + SERVER: { + VIEW_SERVER: 1 << 0, + MANAGE_ROLES: 1 << 1, + MANAGE_CHANNELS: 1 << 2, + MANAGE_SERVER: 1 << 3, + KICK_MEMBERS: 1 << 4, + BAN_MEMBERS: 1 << 5, + CHANGE_NICKNAME: 1 << 12, + MANAGE_NICKNAMES: 1 << 13, + CHANGE_AVATAR: 1 << 14, + REMOVE_AVATARS: 1 << 15, + }, +} as const; export class ChannelPermissions extends BitField { - static FLAGS: typeof FLAGS['CHANNEL'] - constructor(bits?: ChannelPermissionsResolvable) { - super(bits) - } - static resolve(bit: ChannelPermissionsResolvable): number { - return super.resolve(bit) - } + static FLAGS: typeof FLAGS['CHANNEL']; + constructor(bits?: ChannelPermissionsResolvable) { + super(bits); + } + static resolve(bit: ChannelPermissionsResolvable): number { + return super.resolve(bit); + } } -ChannelPermissions.FLAGS = FLAGS.CHANNEL +ChannelPermissions.FLAGS = FLAGS.CHANNEL; export class UserPermissions extends BitField { - static FLAGS: typeof FLAGS['USER'] - constructor(bits?: UserPermissionsResolvable) { - super(bits) - } - static resolve(bit: UserPermissionsResolvable): number { - return super.resolve(bit) - } + static FLAGS: typeof FLAGS['USER']; + constructor(bits?: UserPermissionsResolvable) { + super(bits); + } + static resolve(bit: UserPermissionsResolvable): number { + return super.resolve(bit); + } } -UserPermissions.FLAGS = FLAGS.USER +UserPermissions.FLAGS = FLAGS.USER; export class ServerPermissions extends BitField { - static FLAGS: typeof FLAGS['SERVER'] - constructor(bits?: ServerPermissionsResolvable) { - super(bits) - } - static resolve(bit: ServerPermissionsResolvable): number { - return super.resolve(bit) - } + static FLAGS: typeof FLAGS['SERVER']; + constructor(bits?: ServerPermissionsResolvable) { + super(bits); + } + static resolve(bit: ServerPermissionsResolvable): number { + return super.resolve(bit); + } } -ServerPermissions.FLAGS = FLAGS.SERVER +ServerPermissions.FLAGS = FLAGS.SERVER; export const DEFAULT_PERMISSION_DM = new ChannelPermissions([ - 'VIEW_CHANNEL', - 'VIEW_CHANNEL', - 'MANAGE_CHANNEL', - 'VOICE_CALL', - 'EMBED_LINKS', - 'UPLOAD_FILES' -]).freeze() + 'VIEW_CHANNEL', + 'VIEW_CHANNEL', + 'MANAGE_CHANNEL', + 'VOICE_CALL', + 'EMBED_LINKS', + 'UPLOAD_FILES', +]).freeze(); diff --git a/src/util/UUID.ts b/src/util/UUID.ts index cdccc23..b86ab8f 100644 --- a/src/util/UUID.ts +++ b/src/util/UUID.ts @@ -1,63 +1,63 @@ -import { randomBytes } from 'node:crypto' +import { randomBytes } from 'https://deno.land/std@0.132.0/node/crypto.ts'; export class UUID extends null { - static readonly ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' - static readonly ENCODING_LENGTH = UUID.ENCODING.length - static readonly RANDOM_LENGTH = 16 - static readonly TIME_LENGTH = 10 - static readonly TIME_MAX = Math.pow(2, 48) - 1 - static get PROG(): number { - return randomBytes(1).readUInt8() / 0xff + static readonly ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; + static readonly ENCODING_LENGTH = UUID.ENCODING.length; + static readonly RANDOM_LENGTH = 16; + static readonly TIME_LENGTH = 10; + static readonly TIME_MAX = Math.pow(2, 48) - 1; + static get PROG(): number { + return randomBytes(1).readUInt8() / 0xff; + } + + private static time(now = Date.now()): string { + let mod: number, + result = ''; + + for (let i = this.TIME_LENGTH; i > 0; i--) { + mod = now % this.ENCODING_LENGTH; + result = this.ENCODING.charAt(mod) + result; + now = (now - mod) / this.ENCODING_LENGTH; } - private static time(now = Date.now()): string { - let mod: number, - result = '' + return result; + } - for (let i = this.TIME_LENGTH; i > 0; i--) { - mod = now % this.ENCODING_LENGTH - result = this.ENCODING.charAt(mod) + result - now = (now - mod) / this.ENCODING_LENGTH - } - - return result - } - - private static hash(): string { - let result = '' - - for (let i = this.RANDOM_LENGTH; i > 0; i--) { - let random = Math.floor(this.PROG * this.ENCODING_LENGTH) + private static hash(): string { + let result = ''; - if (random === this.ENCODING_LENGTH) { - random = this.ENCODING_LENGTH - 1 - } + for (let i = this.RANDOM_LENGTH; i > 0; i--) { + let random = Math.floor(this.PROG * this.ENCODING_LENGTH); - result = this.ENCODING.charAt(random) + result - } + if (random === this.ENCODING_LENGTH) { + random = this.ENCODING_LENGTH - 1; + } - return result + result = this.ENCODING.charAt(random) + result; } - static generate(timestamp = Date.now()): string { - return this.time(timestamp) + this.hash() - } + return result; + } - static timestampOf(id: string): Date { - const timestamp = id - .slice(0, this.TIME_LENGTH) - .split('') - .reverse() - .reduce((carry, char, index) => { - const encodingIndex = this.ENCODING.indexOf(char) + static generate(timestamp = Date.now()): string { + return this.time(timestamp) + this.hash(); + } - if (encodingIndex === -1) { - throw new Error('invalid character found: ' + char) - } + static timestampOf(id: string): Date { + const timestamp = id + .slice(0, this.TIME_LENGTH) + .split('') + .reverse() + .reduce((carry, char, index) => { + const encodingIndex = this.ENCODING.indexOf(char); - return (carry += encodingIndex * Math.pow(this.ENCODING_LENGTH, index)) - }, 0) + if (encodingIndex === -1) { + throw new Error('invalid character found: ' + char); + } - return new Date(timestamp) - } + return (carry += encodingIndex * Math.pow(this.ENCODING_LENGTH, index)); + }, 0); + + return new Date(timestamp); + } } diff --git a/src/util/index.ts b/src/util/index.ts deleted file mode 100644 index 6c39be6..0000000 --- a/src/util/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './Badges' -export * from './BitField' -export * from './Collection' -export * from './Constants' -export * from './Permissions' -export * from './UUID' diff --git a/src/util/mod.ts b/src/util/mod.ts new file mode 100644 index 0000000..ca5c9e1 --- /dev/null +++ b/src/util/mod.ts @@ -0,0 +1,6 @@ +export * from './Badges.ts'; +export * from './BitField.ts'; +export * from './Collection.ts'; +export * from './Constants.ts'; +export * from './Permissions.ts'; +export * from './UUID.ts'; diff --git a/transpile.deno.js b/transpile.deno.js deleted file mode 100644 index bafc7b1..0000000 --- a/transpile.deno.js +++ /dev/null @@ -1,50 +0,0 @@ -import fs from 'node:fs' -import path from 'node:path' - -const std = 'https://deno.land/std@0.132.0/' -const root = path.join(process.cwd(), 'deno') - -try { fs.rmSync(root, { recursive: true, force: true }) } catch { } -fs.cpSync('src', root, { recursive: true }) - -const imports = { - 'from \'@discordjs/collection\'': 'from \'https://raw.githubusercontent.com/discordjs/discord.js/main/packages/collection/src/index.ts\'', - 'from \'node:crypto\'': `from '${std}node/crypto.ts'`, - 'import { Response } from \'node-fetch\'': '', - 'import fetch, { Response, HeadersInit } from \'node-fetch\'': '', - 'from \'revolt-api/dist/routes\'': 'from \'https://deno.land/x/revolt_api@0.4.0/routes.ts\'', - 'from \'revolt-api\'': 'from \'https://deno.land/x/revolt_api@0.4.0/types.ts\'', - 'from \'revolt.io\'': 'from \'https://deno.land/x/revoltio/index.ts\'', - 'from \'events\'': `from '${std}node/events.ts'`, - 'import WebSocket from \'ws\'': '', - 'NodeJS.Timer': 'number' -} - -function readdir(dir) { - const dirs = fs.readdirSync(dir); - const files = dirs.map((subdir) => { - const res = path.resolve(dir, subdir); - return fs.statSync(res).isDirectory() ? readdir(res) : res; - }); - return files.reduce((a, f) => a.concat(f), []); -} - -for (const filePath of readdir(root)) { - const content = fs.readFileSync(filePath, 'utf-8') - fs.writeFileSync(filePath, transpile(content)) -} - -fs.writeFileSync(path.join(root, 'README.md'), transpile(fs.readFileSync('README.md', 'utf-8'))) - -function transpile(content) { - for (const [search, replace] of Object.entries(imports)) { - content = content.replace(search, replace) - } - - content = content.replace(/from '(.+)(?\['response'\]>/g, 'Promise') - content = content.replace(/## Installation(\n.*){4}/, '') - content = content.replace(/\[Documentation\](.+)/, '[Documentation](https://doc.deno.land/https://deno.land/x/revoltio/index.ts)') - - return content -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index bb811ad..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "alwaysStrict": true, - "moduleResolution": "node", - "target": "es2019", - "lib": ["ESNext"], - "module": "ESNext", - "declaration": true, - "outDir": "dist", - "incremental": true, - "esModuleInterop": true, - "skipLibCheck": true - }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "examples/**" - ] -}