From 0171b737ccf281499e8715158abe6cf4c18cd4ad Mon Sep 17 00:00:00 2001 From: Jovan Jovanovic Date: Tue, 25 Jan 2022 05:04:34 +0100 Subject: [PATCH] feat: add support for streams --- package-lock.json | 154 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 + src/commands.ts | 31 ++++++++++ src/index.ts | 114 +++++++++++++++++++++++++++++++++- 4 files changed, 293 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index cdf7ccf..daf23a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,8 @@ "dotenv": "^14.2.0" }, "devDependencies": { + "@types/express": "^4.17.13", + "@types/node": "^17.0.11", "typescript": "^4.5.4" } }, @@ -63,10 +65,58 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "node_modules/@types/node": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", - "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==" + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.11.tgz", + "integrity": "sha512-TgLsFcuinMobmML3PsILoRJq/h11/qS7UDlak1LUsazJcvJeKejEBuI1m5X2pBnMBF5T5HRAvtcnr4cV5nvc8Q==" }, "node_modules/@types/node-fetch": { "version": "2.5.12", @@ -90,6 +140,28 @@ "node": ">= 6" } }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", @@ -335,10 +407,58 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz", "integrity": "sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ==" }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "@types/node": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", - "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==" + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.11.tgz", + "integrity": "sha512-TgLsFcuinMobmML3PsILoRJq/h11/qS7UDlak1LUsazJcvJeKejEBuI1m5X2pBnMBF5T5HRAvtcnr4cV5nvc8Q==" }, "@types/node-fetch": { "version": "2.5.12", @@ -361,6 +481,28 @@ } } }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/ws": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.2.tgz", diff --git a/package.json b/package.json index 578097d..8afbf00 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "dotenv": "^14.2.0" }, "devDependencies": { + "@types/express": "^4.17.13", + "@types/node": "^17.0.11", "typescript": "^4.5.4" } } diff --git a/src/commands.ts b/src/commands.ts index a4119d6..86b13e0 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -40,4 +40,35 @@ export const commands = [ new SlashCommandBuilder() .setName("proxylist") .setDescription("List all reverse proxies"), + + new SlashCommandBuilder() + .setName("stream") + .setDescription("Make a stream") + .addStringOption((option) => + option.setName("name").setDescription("Name").setRequired(true) + ) + .addStringOption((option) => + option + .setName("listen") + .setDescription("Listen (Example: 0.0.0.0:8080)") + .setRequired(true) + ) + .addStringOption((option) => + option + .setName("target") + .setDescription("Target (Example: 127.0.0.1:8181)") + .setRequired(true) + ), + new SlashCommandBuilder() + .setName("streamdelete") + .setDescription("Delete a stream") + .addStringOption((option) => + option + .setName("name") + .setDescription("Name of the stream to delete") + .setRequired(true) + ), + new SlashCommandBuilder() + .setName("streamlist") + .setDescription("List all streams"), ]; diff --git a/src/index.ts b/src/index.ts index 71a5c2f..68f14a9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -127,7 +127,7 @@ client.on("interactionCreate", async (interaction): Promise => { }); } else if (interaction.commandName === "proxylist") { const response = await proxy - .get(`/proxies`) + .get(`/proxies`) .then((res) => res.data); if (!response.length) { @@ -148,6 +148,110 @@ client.on("interactionCreate", async (interaction): Promise => { ), ephemeral: true, }); + } else if (interaction.commandName === "streamlist") { + const response = await proxy + .get(`/streams`) + .then((res) => res.data); + + if (!response.length) { + return interaction.reply({ + embeds: [createEmbed("Stream List", "No streams found")], + }); + } + + const text = response + .map((stream) => `${stream.name}: ${stream.listen} -> ${stream.target}`) + .join("\n"); + return interaction.reply({ + embeds: Util.splitMessage(text, { maxLength: 2048 }).map((t) => + createEmbed("Stream List", t) + ), + ephemeral: true, + }); + } else if (interaction.commandName === "stream") { + const name = interaction.options.getString("name"); + const listen = interaction.options.getString("listen"); + const target = interaction.options.getString("target"); + + await interaction.reply({ + embeds: [ + createEmbed( + "Please wait...", + "Creating a stream can take up to 30 seconds." + ), + ], + }); + const response = await proxy + .post<{ + message?: string; + error?: string; + statusCode: number; + }>(`/streams`, { + name, + target, + listen, + }) + .then((r) => r.data) + .catch(console.error); + if (!response) + return interaction.editReply({ + embeds: [createEmbed("Stream", "Something went wrong.")], + }); + + if (response?.statusCode !== 200) { + return interaction + .editReply({ + embeds: [ + createEmbed( + "Error while creating a stream", + response?.error ?? response?.message ?? "Unknown error" + ), + ], + }) + .catch(() => {}); + } + return interaction + .editReply({ + embeds: [ + createEmbed("Stream created", "Successfully created a stream"), + ], + }) + .catch(() => {}); + } else if (interaction.commandName === "streamdelete") { + const name = interaction.options.getString("name"); + + await interaction.reply({ + embeds: [ + createEmbed( + "Please wait...", + "Deleting a stream can take up to 30 seconds." + ), + ], + }); + + const response = await proxy + .delete<{ + error?: string; + message?: string; + statusCode: number; + }>(`/streams/${name}`) + .then((r) => r.data) + .catch(console.error); + + if (response?.statusCode !== 200) { + return interaction.editReply({ + embeds: [ + createEmbed( + "Error while deleting a stream", + response?.error ?? response?.message ?? "Unknown error" + ), + ], + }); + } + + return interaction.editReply({ + embeds: [createEmbed("Stream deleted", "Successfully deleted a stream")], + }); } }); @@ -160,8 +264,14 @@ function createEmbed(title: string, description: string) { .setColor(EMBED_COLOR); } -interface IMetadata { +interface ProxyMetadata { domain: string; target: string; ssl: boolean; } + +interface StreamMetadata { + name: string; + listen: string; + target: string; +}