Compare commits
No commits in common. "9bb30097a40c91fb476af8d6d0480a96b0d111b3" and "8de53c0a23d258592b60a8098295fa2cb15be676" have entirely different histories.
9bb30097a4
...
8de53c0a23
20 changed files with 1049 additions and 1103 deletions
24
.eslintrc
24
.eslintrc
|
@ -7,6 +7,8 @@
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
|
"plugin:import/recommended",
|
||||||
|
"plugin:import/typescript",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"plugin:@typescript-eslint/recommended"
|
"plugin:@typescript-eslint/recommended"
|
||||||
],
|
],
|
||||||
|
@ -120,7 +122,27 @@
|
||||||
{
|
{
|
||||||
"case": "camelCase"
|
"case": "camelCase"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
// Import Rules
|
||||||
|
"import/order": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"newlines-between": "always-and-inside-groups",
|
||||||
|
"groups": [
|
||||||
|
[
|
||||||
|
"builtin",
|
||||||
|
"external",
|
||||||
|
"internal",
|
||||||
|
"parent",
|
||||||
|
"sibling",
|
||||||
|
"index",
|
||||||
|
"object",
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import/newline-after-import": "error"
|
||||||
},
|
},
|
||||||
"reportUnusedDisableDirectives": true
|
"reportUnusedDisableDirectives": true
|
||||||
}
|
}
|
||||||
|
|
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib"
|
||||||
|
}
|
138
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
138
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,5 @@
|
||||||
nodeLinker: node-modules
|
nodeLinker: node-modules
|
||||||
|
|
||||||
nmMode: hardlinks-local
|
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||||
spec: "@yarnpkg/plugin-version"
|
spec: "@yarnpkg/plugin-version"
|
||||||
|
@ -12,4 +10,4 @@ plugins:
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
|
- path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
|
||||||
spec: "@yarnpkg/plugin-typescript"
|
spec: "@yarnpkg/plugin-typescript"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.0.0.cjs
|
yarnPath: .yarn/releases/yarn-sources.cjs
|
||||||
|
|
22
Jenkinsfile
vendored
22
Jenkinsfile
vendored
|
@ -17,18 +17,6 @@ pipeline {
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
stage('Checkout') {
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
echo '==========Checking out=========='
|
|
||||||
if (sh (script: "git log -1 | grep '.*\\[ci skip\\].*'", returnStatus: true)) {
|
|
||||||
error "'[ci skip]' found in git commit message. Aborting."
|
|
||||||
currentBuild.result = 'NOT_BUILT'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stage('Dependencies') {
|
stage('Dependencies') {
|
||||||
steps {
|
steps {
|
||||||
echo '==========Installing Dependencies=========='
|
echo '==========Installing Dependencies=========='
|
||||||
|
@ -47,12 +35,12 @@ pipeline {
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
echo '==========Publishing to NPM=========='
|
echo '==========Publishing to NPM=========='
|
||||||
if (env.BRANCH_NAME == 'master') {
|
if(env.BRANCH_NAME == 'master') {
|
||||||
echo '==========Publishing as Development Version=========='
|
echo '==========Publishing as Development Version=========='
|
||||||
sh 'echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc'
|
sh 'echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc'
|
||||||
sh 'yarn version $(node -pe \'require("./package.json").version\')-$(git rev-parse HEAD).$(date +%s)'
|
sh 'yarn version $(node -pe \'require("./package.json").version\')-$(git rev-parse HEAD).$(date +%s)'
|
||||||
sh 'npm publish --tag dev --access public'
|
sh 'npm publish --tag dev --access public'
|
||||||
} else if (env.BRANCH_NAME == 'stable') {
|
} else if(env.BRANCH_NAME == 'stable') {
|
||||||
echo '==========Publishing as Stable Version=========='
|
echo '==========Publishing as Stable Version=========='
|
||||||
sh 'semantic-release'
|
sh 'semantic-release'
|
||||||
}
|
}
|
||||||
|
@ -66,9 +54,6 @@ pipeline {
|
||||||
cleanWs()
|
cleanWs()
|
||||||
}
|
}
|
||||||
success {
|
success {
|
||||||
sh 'tar -cf - dist/ | xz -9 -c - > neonjs-library.tar.xz'
|
|
||||||
archiveArtifacts artifacts: 'neonjs-library.tar.xz', fingerprint: true
|
|
||||||
|
|
||||||
discordSend description: 'CI build was a Success',
|
discordSend description: 'CI build was a Success',
|
||||||
link: env.BUILD_URL,
|
link: env.BUILD_URL,
|
||||||
result: 'SUCCESS',
|
result: 'SUCCESS',
|
||||||
|
@ -76,9 +61,6 @@ pipeline {
|
||||||
webhookURL: env.DISCORD_WEBHOOK
|
webhookURL: env.DISCORD_WEBHOOK
|
||||||
}
|
}
|
||||||
unstable {
|
unstable {
|
||||||
sh 'tar -cf - dist/ | xz -9 -c - > neonjs-library.tar.xz'
|
|
||||||
archiveArtifacts artifacts: 'neonjs-library.tar.xz', fingerprint: true
|
|
||||||
|
|
||||||
discordSend description: 'CI build was Unstable.',
|
discordSend description: 'CI build was Unstable.',
|
||||||
link: env.BUILD_URL,
|
link: env.BUILD_URL,
|
||||||
result: 'UNSTABLE',
|
result: 'UNSTABLE',
|
||||||
|
|
46
package.json
46
package.json
|
@ -29,7 +29,6 @@
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"commit": "cz",
|
"commit": "cz",
|
||||||
"lint": "eslint --format=pretty src",
|
"lint": "eslint --format=pretty src",
|
||||||
"lint:fix": "eslint --format=pretty src --fix",
|
|
||||||
"postinstall": "husky install",
|
"postinstall": "husky install",
|
||||||
"prepublishOnly": "pinst --disable",
|
"prepublishOnly": "pinst --disable",
|
||||||
"postpublish": "pinst --enable",
|
"postpublish": "pinst --enable",
|
||||||
|
@ -38,19 +37,16 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sapphire/async-queue": "^1.1.4",
|
"@sapphire/async-queue": "^1.1.4",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"cache-manager": "^3.4.4",
|
|
||||||
"cache-manager-ioredis": "^2.1.0",
|
|
||||||
"fast-zlib": "^2.0.1",
|
"fast-zlib": "^2.0.1",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"ioredis": "^4.27.7",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"ws": "^8.0.0"
|
"ws": "^7.5.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^13.1.0",
|
"@commitlint/cli": "^12.1.4",
|
||||||
"@commitlint/config-conventional": "^13.1.0",
|
"@commitlint/config-conventional": "^12.1.4",
|
||||||
"@commitlint/cz-commitlint": "^13.1.0",
|
"@commitlint/cz-commitlint": "^12.1.4",
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||||
"@saithodev/semantic-release-gitea": "^2.1.0",
|
"@saithodev/semantic-release-gitea": "^2.1.0",
|
||||||
"@semantic-release/changelog": "^5.0.1",
|
"@semantic-release/changelog": "^5.0.1",
|
||||||
|
@ -58,36 +54,35 @@
|
||||||
"@semantic-release/git": "^9.0.0",
|
"@semantic-release/git": "^9.0.0",
|
||||||
"@semantic-release/npm": "^7.1.3",
|
"@semantic-release/npm": "^7.1.3",
|
||||||
"@semantic-release/release-notes-generator": "^9.0.3",
|
"@semantic-release/release-notes-generator": "^9.0.3",
|
||||||
"@types/cache-manager": "^3.4.2",
|
|
||||||
"@types/cache-manager-ioredis": "^2.0.2",
|
|
||||||
"@types/chai": "^4.2.21",
|
"@types/chai": "^4.2.21",
|
||||||
"@types/eslint": "^7.28.0",
|
"@types/eslint": "^7.28.0",
|
||||||
"@types/ioredis": "^4.26.7",
|
"@types/lodash": "^4.14.171",
|
||||||
"@types/lodash": "^4.14.172",
|
"@types/mocha": "^8.2.3",
|
||||||
"@types/mocha": "^9.0.0",
|
"@types/node": "^16.3.2",
|
||||||
"@types/node": "^16.4.13",
|
"@types/node-fetch": "^2.5.11",
|
||||||
"@types/node-fetch": "^2.5.12",
|
|
||||||
"@types/semantic-release": "^17.2.1",
|
"@types/semantic-release": "^17.2.1",
|
||||||
"@types/sinon": "^10.0.2",
|
"@types/sinon": "^10.0.2",
|
||||||
"@types/source-map-support": "^0.5.4",
|
"@types/source-map-support": "^0.5.4",
|
||||||
"@types/ws": "^7.4.7",
|
"@types/ws": "^7.4.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
"@typescript-eslint/eslint-plugin": "^4.28.3",
|
||||||
"@typescript-eslint/parser": "^4.29.0",
|
"@typescript-eslint/parser": "^4.28.3",
|
||||||
"@typescript-eslint/typescript-estree": "^4.29.0",
|
"@typescript-eslint/typescript-estree": "^4.28.3",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"commitizen": "^4.2.4",
|
"commitizen": "^4.2.4",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.30.0",
|
||||||
"eslint-formatter-pretty": "^4.1.0",
|
"eslint-formatter-pretty": "^4.1.0",
|
||||||
"eslint-plugin-unicorn": "^35.0.0",
|
"eslint-plugin-header": "^3.1.1",
|
||||||
|
"eslint-plugin-import": "^2.23.4",
|
||||||
|
"eslint-plugin-unicorn": "^34.0.1",
|
||||||
"husky": "^7.0.1",
|
"husky": "^7.0.1",
|
||||||
"inquirer": "^8.1.2",
|
"inquirer": "^8.1.2",
|
||||||
"lint-staged": "^11.1.2",
|
"lint-staged": "^11.0.1",
|
||||||
"mocha": "^9.0.3",
|
"mocha": "^9.0.2",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"pinst": "^2.1.6",
|
"pinst": "^2.1.6",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"semantic-release": "^17.4.4",
|
"semantic-release": "^17.4.4",
|
||||||
"sinon": "^11.1.2",
|
"sinon": "^11.1.1",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"ts-node": "^10.1.0",
|
"ts-node": "^10.1.0",
|
||||||
"tsconfig-paths": "^3.10.1",
|
"tsconfig-paths": "^3.10.1",
|
||||||
|
@ -111,6 +106,5 @@
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
"path": "@commitlint/cz-commitlint"
|
"path": "@commitlint/cz-commitlint"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"packageManager": "yarn@3.0.0"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export class ApiClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async post<T>(options: IRequestOptions): Promise<T> {
|
public async post<T>(options: IRequestOptions): Promise<T> {
|
||||||
return await this.manager.createRequest<T>({
|
return this.manager.createRequest<T>({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: options.body,
|
body: options.body,
|
||||||
headers: options.headers,
|
headers: options.headers,
|
||||||
|
|
|
@ -2,11 +2,12 @@ import { AsyncQueue } from '@sapphire/async-queue';
|
||||||
import { AbortController } from 'abort-controller';
|
import { AbortController } from 'abort-controller';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import type { Client } from '../client/client';
|
|
||||||
import { sleep } from '../utils/sleep';
|
|
||||||
import type { IMakeRequestOptions, IRouteIdentifier } from '../utils/types';
|
|
||||||
import type { ApiManager } from './apiManager';
|
|
||||||
|
|
||||||
|
import { sleep } from '../utils/sleep';
|
||||||
|
|
||||||
|
import type { ApiManager } from './apiManager';
|
||||||
|
import type { Client } from '../client/client';
|
||||||
|
import type { IMakeRequestOptions, IRouteIdentifier } from '../utils/types';
|
||||||
|
|
||||||
function calculateReset(reset: number, resetAfter: number, serverDate: number): number {
|
function calculateReset(reset: number, resetAfter: number, serverDate: number): number {
|
||||||
if (resetAfter) {
|
if (resetAfter) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ApiClient } from './apiClient';
|
import { ApiClient } from './apiClient';
|
||||||
|
|
||||||
import type { Client } from '../client/client';
|
import type { Client } from '../client/client';
|
||||||
import type { IApiCreateMessage, IApiCreateSlashCommand, IApiUser, IFile } from '../utils/types';
|
import type { IApiCreateMessage } from '../utils/types';
|
||||||
|
|
||||||
export class ApiHelper {
|
export class ApiHelper {
|
||||||
public apiClient: ApiClient;
|
public apiClient: ApiClient;
|
||||||
|
@ -16,35 +16,11 @@ export class ApiHelper {
|
||||||
this.apiClient = new ApiClient(this.client, this._token);
|
this.apiClient = new ApiClient(this.client, this._token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Return message object
|
public createMessage(channelId: string, options: IApiCreateMessage): void {
|
||||||
public async createMessage(channelId: string, options: IApiCreateMessage, files?: IFile[]): Promise<void> {
|
this.apiClient.post({
|
||||||
await this.apiClient.post({
|
|
||||||
path: `/channels/${channelId}/messages`,
|
path: `/channels/${channelId}/messages`,
|
||||||
requireAuth: true,
|
requireAuth: true,
|
||||||
body: options,
|
body: options,
|
||||||
files: files,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getCurrentUser(): Promise<IApiUser> {
|
|
||||||
return await this.apiClient.get<IApiUser>({
|
|
||||||
path: '/users/@me',
|
|
||||||
requireAuth: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createSlashCommand(options: IApiCreateSlashCommand): Promise<void> {
|
|
||||||
await this.apiClient.post({
|
|
||||||
path: `/applications/${this.client.user.id}/commands`,
|
|
||||||
requireAuth: true,
|
|
||||||
body: options,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getUser(id: string): Promise<IApiUser> {
|
|
||||||
return await this.apiClient.get<IApiUser>({
|
|
||||||
path: `/users/${id}`,
|
|
||||||
requireAuth: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { Snowflake } from '../utils/snowflake';
|
|
||||||
import { ApiHandler } from './apiHandler';
|
import { ApiHandler } from './apiHandler';
|
||||||
|
import { Snowflake } from '../utils/snowflake';
|
||||||
|
|
||||||
import type { Client } from '../client/client';
|
import type { Client } from '../client/client';
|
||||||
import type { ApiMethods, IMakeRequestOptions, IRouteIdentifier } from '../utils/types';
|
import type { ApiMethods, IMakeRequestOptions, IRouteIdentifier } from '../utils/types';
|
||||||
|
|
||||||
|
|
||||||
export class ApiManager {
|
export class ApiManager {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
public globalReset: number;
|
public globalReset: number;
|
||||||
|
|
|
@ -1,29 +1,27 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
import { ApiHelper } from '../api/apiHelper';
|
import { ApiHelper } from '../api/apiHelper';
|
||||||
import { ClientUser } from '../structures/clientUser';
|
|
||||||
import { GatewayClient } from '../gateway/gatewayClient';
|
import { GatewayClient } from '../gateway/gatewayClient';
|
||||||
import { defaults } from '../utils/defaults';
|
import { defaults } from '../utils/defaults';
|
||||||
|
|
||||||
import type { DeepRequired, IClientOptions } from '../utils/types';
|
import type { DeepRequired, IClientOptions } from '../utils/types';
|
||||||
|
|
||||||
export class Client extends EventEmitter {
|
export class Client extends EventEmitter {
|
||||||
public readonly api: ApiHelper;
|
public api: ApiHelper;
|
||||||
public readonly options: DeepRequired<IClientOptions>;
|
public readonly options: DeepRequired<IClientOptions>;
|
||||||
public readonly user: ClientUser;
|
public ws: GatewayClient;
|
||||||
public readonly ws: GatewayClient;
|
|
||||||
|
|
||||||
private _token: string;
|
private _token: string;
|
||||||
|
|
||||||
public constructor(token: string, options?: IClientOptions) {
|
public constructor(token: string, options: IClientOptions = {}) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.options = _.merge(defaults.clientOptions, options as DeepRequired<IClientOptions>);
|
this.options = _.merge(defaults.clientOptions, options as DeepRequired<IClientOptions>);
|
||||||
this._token = token;
|
this._token = token;
|
||||||
|
|
||||||
this.api = new ApiHelper(this, this._token);
|
this.api = new ApiHelper(this, this._token);
|
||||||
this.user = new ClientUser(this);
|
this.ws = new GatewayClient(this);
|
||||||
this.ws = new GatewayClient(this, this._token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async login(): Promise<void> {
|
public async login(): Promise<void> {
|
||||||
|
|
|
@ -1,37 +1,31 @@
|
||||||
import zlib from 'fast-zlib';
|
import zlib from 'fast-zlib';
|
||||||
import os from 'os';
|
|
||||||
import WebSocket from 'ws';
|
import WebSocket from 'ws';
|
||||||
|
|
||||||
import type { Client } from '../client/client';
|
import type { Client } from '../client/client';
|
||||||
import type { GatewayReceiveMessage, GatewaySendMessage } from '../utils/types';
|
import type { IGatewayMessage } from '../utils/types';
|
||||||
|
|
||||||
|
|
||||||
export class GatewayClient {
|
export class GatewayClient {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
public connection: WebSocket | null;
|
public connection: WebSocket | null;
|
||||||
|
public deflate: zlib.Deflate;
|
||||||
public inflate: zlib.Inflate;
|
public inflate: zlib.Inflate;
|
||||||
|
|
||||||
private _heartbeatInterval: number;
|
|
||||||
private _heartbeatIntervalTimer: NodeJS.Timer | null;
|
|
||||||
private _sequence: number;
|
private _sequence: number;
|
||||||
private _token: string;
|
|
||||||
|
|
||||||
public constructor(client: Client, token: string) {
|
public constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
|
this.deflate = new zlib.Deflate();
|
||||||
this.inflate = new zlib.Inflate();
|
this.inflate = new zlib.Inflate();
|
||||||
|
|
||||||
this._heartbeatInterval = 0;
|
|
||||||
this._heartbeatIntervalTimer= null;
|
|
||||||
this._sequence = 0;
|
this._sequence = 0;
|
||||||
this._token= token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async close(): Promise<void> {
|
public async close(): Promise<void> {
|
||||||
if (!this.connection) throw new Error('You are not connected to the Discord WebSocket Gateway!');
|
if (!this.connection) throw new Error('You are not connected to the Discord WebSocket Gateway!');
|
||||||
|
|
||||||
this.connection.close(1000);
|
this.connection.close(1000);
|
||||||
if (this._heartbeatIntervalTimer) clearTimeout(this._heartbeatIntervalTimer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async connect(): Promise<void> {
|
public async connect(): Promise<void> {
|
||||||
|
@ -42,50 +36,13 @@ export class GatewayClient {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.connection.on('message', async (msg: Buffer | string) => {
|
this.connection.on('message', async (msg: Buffer | string) => {
|
||||||
let parsedMessage: GatewayReceiveMessage;
|
let parsedMessage: IGatewayMessage<null>;
|
||||||
|
|
||||||
if (this.client.options.ws.compression && typeof msg === 'object') parsedMessage = JSON.parse(this.inflate.process(msg).toString('utf8'));
|
if (this.client.options.ws.compression && typeof msg === 'object') parsedMessage = JSON.parse(this.inflate.process(msg).toString('utf8'));
|
||||||
else if (!this.client.options.ws.compression && typeof msg === 'string') parsedMessage = JSON.parse(msg);
|
else if (!this.client.options.ws.compression && typeof msg === 'string') parsedMessage = JSON.parse(msg);
|
||||||
else parsedMessage = JSON.parse(msg.toString('utf8'));
|
else parsedMessage = JSON.parse(msg.toString('utf8'));
|
||||||
|
|
||||||
// if (parsedMessage.s) this._sequence = parsedMessage.s;
|
if (parsedMessage.s) this._sequence = parsedMessage.s;
|
||||||
|
|
||||||
this.client.emit('raw', parsedMessage);
|
|
||||||
|
|
||||||
switch (parsedMessage.op) {
|
|
||||||
case 10:
|
|
||||||
this._heartbeatInterval = parsedMessage.d.heartbeat_interval;
|
|
||||||
|
|
||||||
this.send({
|
|
||||||
op: 2, d: {
|
|
||||||
compress: this.client.options.ws.compression,
|
|
||||||
intents: this.client.options.ws.intents,
|
|
||||||
large_threshold: this.client.options.ws.largeThreshold,
|
|
||||||
presence: this.client.options.presence,
|
|
||||||
properties: {
|
|
||||||
$browser: '@neonjs/library',
|
|
||||||
$device: '@neonjs/library',
|
|
||||||
$os: os.platform(),
|
|
||||||
},
|
|
||||||
token: this._token,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this._heartbeatIntervalTimer = setInterval(() => this._sendHeartbeat(), this._heartbeatInterval * 1000);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public send(data: GatewaySendMessage): void {
|
|
||||||
if (!this.connection) throw new Error('You are not connected to the Discord WebSocket Gateway!');
|
|
||||||
|
|
||||||
this.connection.send(JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
private _sendHeartbeat(): void {
|
|
||||||
this.send({ op: 1, d: this._sequence });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { User } from './user';
|
|
||||||
|
|
||||||
import type { Client } from '../client/client';
|
|
||||||
|
|
||||||
export class ClientUser extends User {
|
|
||||||
public constructor(client: Client) {
|
|
||||||
super(client);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
import type { IApiUser } from '..';
|
|
||||||
import type { Client } from '../client/client';
|
|
||||||
|
|
||||||
export class User {
|
|
||||||
public client: Client;
|
|
||||||
public id: string;
|
|
||||||
|
|
||||||
private _options: IApiUser;
|
|
||||||
|
|
||||||
public constructor(client: Client, options: IApiUser) {
|
|
||||||
this.client = client;
|
|
||||||
this._options = options;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async fetch(id: string): Promise<IApiUser> {
|
|
||||||
return this.client.api.getUser(id);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
import cacheManager from 'cache-manager';
|
|
||||||
import redisStore from 'cache-manager-ioredis';
|
|
||||||
|
|
||||||
import type { Client } from '../client/client';
|
|
||||||
|
|
||||||
export class CacheManager {
|
|
||||||
public client: Client;
|
|
||||||
|
|
||||||
private readonly _cacheManager: cacheManager.Cache;
|
|
||||||
|
|
||||||
public constructor(client: Client) {
|
|
||||||
this.client = client;
|
|
||||||
|
|
||||||
if (this.client.options.cache.cache === 'redis') this._cacheManager = cacheManager.caching({
|
|
||||||
store: redisStore,
|
|
||||||
ttl: this.client.options.cache.ttl,
|
|
||||||
...this.client.options.cache.options,
|
|
||||||
});
|
|
||||||
else this._cacheManager = cacheManager.caching({
|
|
||||||
store: 'memory',
|
|
||||||
ttl: this.client.options.cache.ttl,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async del(key: string): Promise<void> {
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
this._cacheManager.del(key, (err) => {
|
|
||||||
if (err) rej(err);
|
|
||||||
else res();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async get<T>(key: string): Promise<T | undefined> {
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
this._cacheManager.get<T>(key, (err, result) => {
|
|
||||||
if (err) rej(err);
|
|
||||||
else res(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async set<T>(key: string, value: T): Promise<T> {
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
this._cacheManager.set<T>(key, value, this.client.options.cache.ttl, (err) => {
|
|
||||||
if (err) rej(err);
|
|
||||||
else res(value);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,16 +10,9 @@ export const defaults: IDefaultOptions = {
|
||||||
url: 'https://discord.com/api',
|
url: 'https://discord.com/api',
|
||||||
version: 9,
|
version: 9,
|
||||||
},
|
},
|
||||||
cache: {
|
|
||||||
cache: 'memory',
|
|
||||||
ttl: 60,
|
|
||||||
},
|
|
||||||
presence: {},
|
|
||||||
ws: {
|
ws: {
|
||||||
compression: true,
|
compression: true,
|
||||||
encoding: 'json',
|
encoding: 'json',
|
||||||
intents: 0,
|
|
||||||
largeThreshold: 250,
|
|
||||||
url: 'wss://gateway.discord.gg',
|
url: 'wss://gateway.discord.gg',
|
||||||
version: 9,
|
version: 9,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import type IORedis from 'ioredis';
|
|
||||||
|
|
||||||
// Interfaces
|
// Interfaces
|
||||||
export interface IApiClientOptions {
|
export interface IApiClientOptions {
|
||||||
offset?: number;
|
offset?: number;
|
||||||
|
@ -10,21 +8,8 @@ export interface IApiClientOptions {
|
||||||
version?: number;
|
version?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICacheMemoryClientOptions {
|
|
||||||
cache?: 'memory';
|
|
||||||
ttl?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICacheRedisClientOptions {
|
|
||||||
cache?: 'redis';
|
|
||||||
ttl?: number;
|
|
||||||
options: IORedis.RedisOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IClientOptions {
|
export interface IClientOptions {
|
||||||
api?: IApiClientOptions;
|
api?: IApiClientOptions;
|
||||||
cache?: ICacheMemoryClientOptions | ICacheRedisClientOptions;
|
|
||||||
presence?: IUpdatePresence;
|
|
||||||
ws?: IWebSocketClientOptions;
|
ws?: IWebSocketClientOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,64 +56,16 @@ export interface IRouteIdentifier {
|
||||||
route: string;
|
route: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUpdatePresence {
|
|
||||||
activities?: {
|
|
||||||
name?: string;
|
|
||||||
type?: EActivityType;
|
|
||||||
url?: string;
|
|
||||||
}[];
|
|
||||||
afk?: boolean;
|
|
||||||
since?: number;
|
|
||||||
status?: EStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IWebSocketClientOptions {
|
export interface IWebSocketClientOptions {
|
||||||
compression?: boolean;
|
compression?: boolean;
|
||||||
encoding?: 'json';
|
encoding?: 'json';
|
||||||
intents?: number;
|
|
||||||
largeThreshold?: number;
|
|
||||||
url?: string;
|
url?: string;
|
||||||
version?: number;
|
version?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Api Interfaces
|
// Api Rest Request Interfaces
|
||||||
// TODO: Add message components
|
// TODO: Add message components
|
||||||
// Dont add the files option. That goes into a separate option when creating a request
|
|
||||||
export interface IApiCreateMessage {
|
export interface IApiCreateMessage {
|
||||||
allowed_mentions?: {
|
|
||||||
parse?: 'everyone' | 'roles' | 'users'[];
|
|
||||||
replied_user?: boolean;
|
|
||||||
roles?: string[];
|
|
||||||
users?: string[];
|
|
||||||
};
|
|
||||||
content?: string;
|
|
||||||
embeds?: IMessageEmbed[];
|
|
||||||
message_reference?: {
|
|
||||||
channel_id?: string;
|
|
||||||
fail_if_not_exists?: boolean;
|
|
||||||
guild_id?: string;
|
|
||||||
message_id?: string;
|
|
||||||
};
|
|
||||||
tts?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IApiUser {
|
|
||||||
avatar: string;
|
|
||||||
bot?: boolean;
|
|
||||||
discriminator: string;
|
|
||||||
email?: string;
|
|
||||||
flags?: number;
|
|
||||||
id: string;
|
|
||||||
locale?: string;
|
|
||||||
mfa_enabled?: boolean;
|
|
||||||
premium_type?: number;
|
|
||||||
public_flags?: number;
|
|
||||||
username: string;
|
|
||||||
system?: boolean;
|
|
||||||
verified?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IApiCreateSlashCommand {
|
|
||||||
allowed_mentions?: {
|
allowed_mentions?: {
|
||||||
parse?: 'everyone' | 'roles' | 'users'[];
|
parse?: 'everyone' | 'roles' | 'users'[];
|
||||||
replied_user?: boolean;
|
replied_user?: boolean;
|
||||||
|
@ -148,55 +85,14 @@ export interface IApiCreateSlashCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebSocket Gateway Message Interfaces
|
// WebSocket Gateway Message Interfaces
|
||||||
export interface IGatewayHeartbeatSend {
|
export interface IGatewayMessage<T> {
|
||||||
op: 1;
|
d?: T;
|
||||||
d: number;
|
op: number;
|
||||||
}
|
s?: number;
|
||||||
|
t?: string;
|
||||||
// TODO: Add sharding when i get to it
|
|
||||||
export interface IGatewayIdentify {
|
|
||||||
op: 2;
|
|
||||||
d: {
|
|
||||||
compress: boolean;
|
|
||||||
intents: number;
|
|
||||||
large_threshold: number;
|
|
||||||
presence?: IUpdatePresence;
|
|
||||||
properties: {
|
|
||||||
$browser: string;
|
|
||||||
$device: string;
|
|
||||||
$os: string;
|
|
||||||
};
|
|
||||||
token: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IGatewayHeartbeat {
|
|
||||||
op: 10;
|
|
||||||
d: {
|
|
||||||
heartbeat_interval: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IGatewayHeartbeatAck {
|
|
||||||
op: 11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
export enum EActivityType {
|
|
||||||
GAME = 0,
|
|
||||||
STREAMING = 1,
|
|
||||||
LISTENING = 2,
|
|
||||||
WATCHING = 3,
|
|
||||||
COMPETING = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum EStatus {
|
|
||||||
DND = 'dnd',
|
|
||||||
IDLE = 'idle',
|
|
||||||
INVISIBLE = 'invisible',
|
|
||||||
OFFLINE = 'offline',
|
|
||||||
ONLINE = 'online',
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type Aliases
|
// Type Aliases
|
||||||
export type ApiMethods = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT' ;
|
export type ApiMethods = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT' ;
|
||||||
|
@ -222,6 +118,4 @@ export type DeepRequired<T> = T extends Builtin
|
||||||
: T extends {}
|
: T extends {}
|
||||||
? { [K in keyof T]-?: DeepRequired<T[K]> }
|
? { [K in keyof T]-?: DeepRequired<T[K]> }
|
||||||
: NonNullable<T>;
|
: NonNullable<T>;
|
||||||
export type GatewayReceiveMessage = IGatewayHeartbeat | IGatewayHeartbeatAck;
|
|
||||||
export type GatewaySendMessage = IGatewayHeartbeatSend | IGatewayIdentify;
|
|
||||||
export type Primitives = bigint | boolean | null | number | string | symbol | undefined;
|
export type Primitives = bigint | boolean | null | number | string | symbol | undefined;
|
||||||
|
|
Reference in a new issue