first commit
This commit is contained in:
commit
dd996aecaf
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
46
README.md
Normal file
46
README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# SSH Chat
|
||||
|
||||
A Peer to Peer chat client using Hyper-Protocol.
|
||||
|
||||
To install:
|
||||
|
||||
`git clone git@git.codingvm.codes:snxraven/sshChat-CLI.git`
|
||||
|
||||
`cd sshChat-CLI`
|
||||
|
||||
`npm i`
|
||||
|
||||
To run a new topic (room):
|
||||
|
||||
`node sshchat.mjs`
|
||||
|
||||
This will give you a connection topic to share:
|
||||
|
||||
```
|
||||
/sshChat ❯ ✦ node sshChat.mjs
|
||||
joined topic: 6076c0903ad293e24c10fceb501fe7b02425f6d26c7a5b2d015abd07e3e6b17b
|
||||
(Share this key to others so they may join.)
|
||||
You are now in a chatroom for your topic, feel free to chat.
|
||||
```
|
||||
|
||||
|
||||
To connect to an altready made topic (room) pass the hash on start up:
|
||||
|
||||
|
||||
`node sshchat.mjs 6076c0903ad293e24c10fceb501fe7b02425f6d26c7a5b2d015abd07e3e6b17b`
|
||||
|
||||
# Commands
|
||||
|
||||
/login [API KEY] - Login to the API
|
||||
|
||||
> command here - Send a command to your container
|
||||
|
||||
/start - Start your container
|
||||
|
||||
/stop - Stop your container
|
||||
|
||||
/restart - restart your container
|
||||
|
||||
/stats - Get the containers stats
|
||||
|
||||
If a user does not login they will have a random annon1234 username.
|
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "sshchat",
|
||||
"version": "1.0.0",
|
||||
"description": "A peer to peer chat client that uses hyper-protocol and connects to the ssh.surf API",
|
||||
"main": "sshChat.mjs",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.codingvm.codes:snxraven/sshChat-CLI.git"
|
||||
},
|
||||
"author": "Raven Scott",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"b4a": "^1.6.1",
|
||||
"graceful-goodbye": "^1.2.0",
|
||||
"hypercore-crypto": "^3.3.0",
|
||||
"hyperswarm": "^4.3.5",
|
||||
"readline": "^1.3.0",
|
||||
"unirest": "^0.6.0"
|
||||
}
|
||||
}
|
200
sshChat.mjs
Normal file
200
sshChat.mjs
Normal file
@ -0,0 +1,200 @@
|
||||
|
||||
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 = {}
|
||||
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("!", "")
|
||||
}
|
||||
|
||||
async function runCMD(key, cmd, pwd){
|
||||
let requestData = await unirest
|
||||
.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})
|
||||
return requestData.body.stdout
|
||||
}
|
||||
|
||||
async function startContainer(key){
|
||||
let startContainer = await unirest
|
||||
.get('https://api.discord-linux.com/start')
|
||||
.headers({'Accept': 'application/json', 'Content-Type': 'application/json',
|
||||
'x-discord-linux-auth': key})
|
||||
return startContainer.body.completed
|
||||
}
|
||||
|
||||
|
||||
async function stopContainer(key){
|
||||
let stopContainer = await unirest
|
||||
.get('https://api.discord-linux.com/stop')
|
||||
.headers({'Accept': 'application/json', 'Content-Type': 'application/json',
|
||||
'x-discord-linux-auth': key})
|
||||
return stopContainer.body.completed
|
||||
}
|
||||
|
||||
async function restartContainer(key){
|
||||
let restartContainer = await unirest
|
||||
.get('https://api.discord-linux.com/restart')
|
||||
.headers({'Accept': 'application/json', 'Content-Type': 'application/json',
|
||||
'x-discord-linux-auth': key})
|
||||
return restartContainer.body.completed
|
||||
}
|
||||
|
||||
async function getStats(key){
|
||||
let getStats = await unirest
|
||||
.get('https://api.discord-linux.com/restart')
|
||||
.headers({'Accept': 'application/json', 'Content-Type': 'application/json',
|
||||
'x-discord-linux-auth': key})
|
||||
console.log(getStats.body)
|
||||
return getStats.body.data
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
console.log(`Weclcome ${USERNAME} you are now logged in!`)
|
||||
return LOGGEDIN = true
|
||||
});
|
||||
}
|
||||
|
||||
const execute = input.startsWith(">")
|
||||
if (execute) {
|
||||
let inputdata = input.split(2)
|
||||
const cmdToRun = inputdata.join(" ").replace("> ", "").replace(">","")
|
||||
runCMD(DAPI_KEY.key, cmdToRun, "/").then((data) => {
|
||||
console.log(data)
|
||||
for (const conn of conns) {
|
||||
conn.write(`${USERNAME} ran ${cmdToRun}: \n` + data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const start = input.match(/^\/start (\S+)$/)
|
||||
if (start) {
|
||||
const cmdToRun = start[1]
|
||||
startContainer(DAPI_KEY.key).then((data) => {
|
||||
for (const conn of conns) {
|
||||
console.log(data)
|
||||
conn.write(`${USERNAME} ran start: \n` + data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const stop = input.match(/^\/stop (\S+)$/)
|
||||
if (stop) {
|
||||
const cmdToRun = stop[1]
|
||||
stopContainer(DAPI_KEY.key).then((data) => {
|
||||
for (const conn of conns) {
|
||||
console.log(data)
|
||||
conn.write(`${USERNAME} ran stop: \n` + data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const restart = input.match(/^\/restart (\S+)$/)
|
||||
if (restart) {
|
||||
const restart = restart[1]
|
||||
restartContainer(DAPI_KEY.key).then((data) => {
|
||||
for (const conn of conns) {
|
||||
console.log(data)
|
||||
conn.write(`${USERNAME} ran restart: \n` + data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const stats = input.match(/^\/stats (\S+)$/)
|
||||
if (stats) {
|
||||
const stats = stats[1]
|
||||
getStats(DAPI_KEY.key).then((data) => {
|
||||
for (const conn of conns) {
|
||||
console.log(data)
|
||||
conn.write(`${USERNAME} ran stats: \n` + data)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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.')
|
||||
})
|
Loading…
Reference in New Issue
Block a user