2023-01-08 22:03:13 -05:00
|
|
|
|
|
|
|
import Hyperswarm from 'hyperswarm'
|
|
|
|
import goodbye from 'graceful-goodbye'
|
|
|
|
import crypto from 'hypercore-crypto'
|
|
|
|
import b4a from 'b4a'
|
|
|
|
import readline from 'readline'
|
|
|
|
import unirest from "unirest";
|
|
|
|
let rand = Math.floor(Math.random() * 99999).toString();
|
|
|
|
|
|
|
|
// Generate a random public key
|
|
|
|
const publicKey = crypto.randomBytes(32)
|
|
|
|
|
|
|
|
// Create the swarm and pass in the public key
|
|
|
|
const swarm = new Hyperswarm()
|
|
|
|
goodbye(() => swarm.destroy())
|
|
|
|
|
|
|
|
// Keep track of all connections and USERNAMEs
|
|
|
|
const conns = []
|
|
|
|
const names = {}
|
2023-01-08 22:59:49 -05:00
|
|
|
let USERPWD = "/"
|
2023-01-08 22:03:13 -05:00
|
|
|
let DAPI_KEY = {}
|
|
|
|
let USERNAME = "annon" + rand
|
|
|
|
let LOGGEDIN = false
|
|
|
|
|
|
|
|
async function clearCursor() {
|
|
|
|
readline.moveCursor(process.stdout, 0, -2) // up one line
|
|
|
|
readline.clearLine(process.stdout, 0) // from cursor to end
|
|
|
|
readline.moveCursor(process.stdout, 0, 2) // up one line
|
|
|
|
}
|
|
|
|
|
|
|
|
// API Functions
|
|
|
|
async function getUSERNAME(key) {
|
|
|
|
let requestUSERNAME = await unirest
|
|
|
|
.get('https://api.discord-linux.com/hello')
|
|
|
|
.headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', 'x-discord-linux-auth': key })
|
|
|
|
return requestUSERNAME.body.message.replace("Hello, ", "").replace("!", "")
|
|
|
|
}
|
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
async function runCMD(key, cmd, pwd) {
|
2023-01-08 22:03:13 -05:00
|
|
|
let requestData = await unirest
|
2023-01-08 22:59:49 -05:00
|
|
|
.post('https://api.discord-linux.com/exec')
|
|
|
|
.headers({
|
|
|
|
'Accept': 'application/json', 'Content-Type': 'application/json',
|
|
|
|
'x-discord-linux-auth': key
|
|
|
|
})
|
|
|
|
.send({ "cmd": cmd, "pwd": pwd })
|
2023-01-08 22:03:13 -05:00
|
|
|
return requestData.body.stdout
|
|
|
|
}
|
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
async function startContainer(key) {
|
2023-01-08 22:03:13 -05:00
|
|
|
let startContainer = await unirest
|
2023-01-08 22:59:49 -05:00
|
|
|
.get('https://api.discord-linux.com/start')
|
|
|
|
.headers({
|
|
|
|
'Accept': 'application/json', 'Content-Type': 'application/json',
|
|
|
|
'x-discord-linux-auth': key
|
|
|
|
})
|
2023-01-08 23:39:13 -05:00
|
|
|
return startContainer.body
|
2023-01-08 22:03:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
async function stopContainer(key) {
|
2023-01-08 22:03:13 -05:00
|
|
|
let stopContainer = await unirest
|
2023-01-08 22:59:49 -05:00
|
|
|
.get('https://api.discord-linux.com/stop')
|
|
|
|
.headers({
|
|
|
|
'Accept': 'application/json', 'Content-Type': 'application/json',
|
|
|
|
'x-discord-linux-auth': key
|
|
|
|
})
|
2023-01-08 23:39:13 -05:00
|
|
|
return stopContainer.body
|
2023-01-08 22:03:13 -05:00
|
|
|
}
|
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
async function restartContainer(key) {
|
2023-01-08 22:03:13 -05:00
|
|
|
let restartContainer = await unirest
|
2023-01-08 22:59:49 -05:00
|
|
|
.get('https://api.discord-linux.com/restart')
|
|
|
|
.headers({
|
|
|
|
'Accept': 'application/json', 'Content-Type': 'application/json',
|
|
|
|
'x-discord-linux-auth': key
|
|
|
|
})
|
2023-01-08 23:39:13 -05:00
|
|
|
return restartContainer.body
|
2023-01-08 22:03:13 -05:00
|
|
|
}
|
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
async function getStats(key) {
|
2023-01-08 22:03:13 -05:00
|
|
|
let getStats = await unirest
|
2023-01-08 23:39:13 -05:00
|
|
|
.get('https://api.discord-linux.com/stats')
|
2023-01-08 22:59:49 -05:00
|
|
|
.headers({
|
|
|
|
'Accept': 'application/json', 'Content-Type': 'application/json',
|
|
|
|
'x-discord-linux-auth': key
|
|
|
|
})
|
2023-01-08 23:39:13 -05:00
|
|
|
return getStats.body
|
2023-01-08 22:03:13 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
swarm.on('connection', conn => {
|
|
|
|
const name = b4a.toString(conn.remotePublicKey, 'hex')
|
|
|
|
console.log(`* got a connection from ${name} (${USERNAME}) *`)
|
|
|
|
conns.push(conn)
|
|
|
|
conn.once('close', () => conns.splice(conns.indexOf(conn), 1))
|
|
|
|
conn.on('data', data => {
|
|
|
|
// Use the USERNAME if it has been set, otherwise use the public key
|
|
|
|
console.log(`${data}`)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
// Use readline to accept input from the user
|
|
|
|
const rl = readline.createInterface({
|
|
|
|
input: process.stdin,
|
|
|
|
output: process.stdout
|
|
|
|
})
|
|
|
|
|
|
|
|
// When the user inputs a line of text, broadcast it to all connections
|
|
|
|
rl.on('line', input => {
|
|
|
|
|
|
|
|
|
|
|
|
const signIn = input.match(/^\/login (\S+)$/)
|
|
|
|
if (signIn) {
|
|
|
|
const APIKEY = signIn[1]
|
|
|
|
DAPI_KEY = { "key": APIKEY }
|
|
|
|
getUSERNAME(APIKEY).then((data) => {
|
|
|
|
USERNAME = data
|
|
|
|
// const name = b4a.toString(publicKey, 'hex')
|
|
|
|
// names[name] = USERNAME
|
|
|
|
for (const conn of conns) {
|
|
|
|
conn.write(`${USERNAME} has logged in!`)
|
|
|
|
}
|
|
|
|
clearCursor()
|
2023-01-08 22:59:49 -05:00
|
|
|
console.log(`Welcome ${USERNAME} you are now logged in!`)
|
2023-01-08 22:03:13 -05:00
|
|
|
return LOGGEDIN = true
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-01-08 22:59:49 -05:00
|
|
|
const changeDir = input.startsWith(">cd") || input.startsWith("> cd")
|
|
|
|
if (changeDir) {
|
|
|
|
const commandArgs = input.replace("> cd ", "").replace(">cd", "").replace(" ", "")
|
|
|
|
if (commandArgs.startsWith("/")) {
|
|
|
|
USERPWD = commandArgs;
|
|
|
|
console.log("Directory Changed to: " + USERPWD)
|
|
|
|
} else {
|
|
|
|
USERPWD = USERPWD + "/" + commandArgs;
|
|
|
|
console.log("Directory Changed to: " + USERPWD)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-08 22:03:13 -05:00
|
|
|
const execute = input.startsWith(">")
|
|
|
|
if (execute) {
|
|
|
|
let inputdata = input.split(2)
|
2023-01-08 22:59:49 -05:00
|
|
|
const cmdToRun = inputdata.join(" ").replace("> ", "").replace(">", "")
|
|
|
|
if (cmdToRun.includes("cd")) return
|
2023-01-08 22:03:13 -05:00
|
|
|
runCMD(DAPI_KEY.key, cmdToRun, "/").then((data) => {
|
|
|
|
console.log(data)
|
|
|
|
for (const conn of conns) {
|
|
|
|
conn.write(`${USERNAME} ran ${cmdToRun}: \n` + data)
|
|
|
|
}
|
2023-01-08 22:59:49 -05:00
|
|
|
})
|
|
|
|
}
|
2023-01-08 22:03:13 -05:00
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
const start = input.startsWith("/start")
|
2023-01-08 22:59:49 -05:00
|
|
|
if (start) {
|
|
|
|
startContainer(DAPI_KEY.key).then((data) => {
|
2023-01-08 23:39:13 -05:00
|
|
|
console.log(data)
|
2023-01-08 22:59:49 -05:00
|
|
|
for (const conn of conns) {
|
2023-01-08 23:41:53 -05:00
|
|
|
conn.write(`${USERNAME} ran start.`)
|
2023-01-08 22:59:49 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2023-01-08 22:03:13 -05:00
|
|
|
|
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
const stop = input.startsWith("/stop")
|
2023-01-08 22:59:49 -05:00
|
|
|
if (stop) {
|
2023-01-08 23:39:13 -05:00
|
|
|
startContainer(DAPI_KEY.key).then((data) => {
|
|
|
|
console.log(data)
|
2023-01-08 22:59:49 -05:00
|
|
|
for (const conn of conns) {
|
2023-01-08 23:41:53 -05:00
|
|
|
conn.write(`${USERNAME} ran stop.`)
|
2023-01-08 22:59:49 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2023-01-08 22:03:13 -05:00
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
|
|
|
|
const restart = input.startsWith("/restart")
|
2023-01-08 22:59:49 -05:00
|
|
|
if (restart) {
|
2023-01-08 23:39:13 -05:00
|
|
|
startContainer(DAPI_KEY.key).then((data) => {
|
|
|
|
console.log(data)
|
2023-01-08 22:59:49 -05:00
|
|
|
for (const conn of conns) {
|
2023-01-08 23:41:53 -05:00
|
|
|
conn.write(`${USERNAME} ran restart.`)
|
2023-01-08 22:59:49 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2023-01-08 22:03:13 -05:00
|
|
|
|
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
|
|
|
|
const stats = input.startsWith("/stats")
|
2023-01-08 22:59:49 -05:00
|
|
|
if (stats) {
|
|
|
|
getStats(DAPI_KEY.key).then((data) => {
|
2023-01-08 23:39:13 -05:00
|
|
|
console.log(data)
|
2023-01-08 22:59:49 -05:00
|
|
|
for (const conn of conns) {
|
2023-01-08 23:41:53 -05:00
|
|
|
conn.write(`${USERNAME} ran stats.`)
|
2023-01-08 22:59:49 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2023-01-08 22:03:13 -05:00
|
|
|
|
2023-01-08 23:39:13 -05:00
|
|
|
|
2023-01-08 22:03:13 -05:00
|
|
|
else {
|
|
|
|
// if (!LOGGEDIN) return console.log("Please login using /login [API KEY]")
|
|
|
|
if (input.match(/^\/login (\S+)$/)) return
|
|
|
|
for (const conn of conns) {
|
|
|
|
conn.write(`${USERNAME}: ${input}`)
|
|
|
|
}
|
|
|
|
console.log(`${USERNAME}: ${input}`)
|
|
|
|
// Clear the input line\
|
|
|
|
clearCursor()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// Join a common topic
|
|
|
|
const topic = process.argv[2] ? b4a.from(process.argv[2], 'hex') : crypto.randomBytes(32)
|
|
|
|
const discovery = swarm.join(topic, { client: true, server: true })
|
|
|
|
|
|
|
|
// The flushed promise will resolve when the topic has been fully announced to the DHT
|
|
|
|
discovery.flushed().then(() => {
|
|
|
|
console.log(`joined topic: ${b4a.toString(topic, 'hex')}\n(Share this key to others so they may join.)`)
|
|
|
|
console.log('You are now in a chatroom for your topic, feel free to chat.\n')
|
|
|
|
console.log('Want to login to the SSH.SURF API? Type "/login [APIKEY]" to login.')
|
2023-01-08 22:23:46 -05:00
|
|
|
})
|