Compare commits

..

12 Commits

5 changed files with 121 additions and 64 deletions

View File

@ -70,10 +70,8 @@ To connect to an altready made topic (room) pass the hash on start up:
## Screenshots: ## Screenshots:
A simple convo: A simple convo:
![ScreenShot](https://media.discordapp.net/attachments/818514972610134069/1061846943556435978/Unsaved_Image_1.jpg?width=1215&height=660) ![ScreenShot](https://media.discordapp.net/attachments/1025463055016001546/1069366373576360077/image.png?width=1202&height=660)
Running commands while logged in:
![ScreenShot](https://media.discordapp.net/attachments/818514972610134069/1061839208064495617/Unsaved_Image_1.jpg?width=1215&height=660)
If a user does not login they will have a random annon1234 username. If a user does not login they will have a random annon1234 username.

View File

@ -1,5 +1,4 @@
// AI.js // AI.js
var unirest = require('unirest'); var unirest = require('unirest');
async function AIRequest(prompt) { async function AIRequest(prompt) {
@ -12,5 +11,4 @@ async function AIRequest(prompt) {
return AIRequest.body.bot return AIRequest.body.bot
} }
module.exports = { AIRequest } module.exports = { AIRequest }

View File

@ -12,7 +12,7 @@ async function runCMD(key, cmd, pwd) {
return requestData.body.stdout return requestData.body.stdout
} }
async function execute(key, cmd, pwd, conns) { async function execute(key, cmd, pwd, conns, USERNAME) {
const stdout = await runCMD(key, cmd, pwd) const stdout = await runCMD(key, cmd, pwd)
console.log(stdout) console.log(stdout)
if (stdout.length > 1800) return console.log("I cannot send stdout to the swarm, its too large!") if (stdout.length > 1800) return console.log("I cannot send stdout to the swarm, its too large!")

View File

@ -1,16 +1,20 @@
var unirest = require('unirest'); var unirest = require('unirest');
async function login(key, conns, MYKEY, USERNAME) { async function login(key, conns, MYKEY, USERNAME, DISCORD_USERID) {
getUSERNAME(key) getUSERNAME(key)
.then((data) => { .then((data) => {
console.log("Hello, " + data + "\nYou are now logged in.\n\n\n") console.log("Hello, " + data + "\nYou are now logged in.\n\n\n")
USERNAME[0] = data USERNAME[0] = data
MYKEY.push(key) MYKEY.push(key)
LOGGEDIN = true LOGGEDIN = true
getDISCORDID(key)
.then((discord) => {
DISCORD_USERID[0] = [discord]
for (const conn of conns) { for (const conn of conns) {
conn.write(`${USERNAME} is now logged in.`) conn.write(`${USERNAME} | <@${discord}> is now logged in.`)
} }
}) })
})
.catch(err => { .catch(err => {
console.log("Invalid Key") console.log("Invalid Key")
for (const conn of conns) { for (const conn of conns) {
@ -23,9 +27,16 @@ async function login(key, conns, MYKEY, USERNAME) {
// API Functions // API Functions
async function getUSERNAME(key) { async function getUSERNAME(key) {
let requestUSERNAME = await unirest let requestUSERNAME = await unirest
.get('https://api.discord-linux.com/hello') .get('https://api.discord-linux.com/name')
.headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', 'x-discord-linux-auth': key }) .headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', 'x-discord-linux-auth': key })
return requestUSERNAME.body.message.replace("Hello, ", "").replace("!", "") return requestUSERNAME.body.message
}
async function getDISCORDID(key) {
let requestUSERNAME = await unirest
.get('https://api.discord-linux.com/discordid')
.headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', 'x-discord-linux-auth': key })
return requestUSERNAME.body.message
} }
module.exports = { login } module.exports = { login }

View File

@ -1,12 +1,13 @@
const blessed = require('neo-blessed');
// Require the needed libs // Require the needed libs
const blessed = require('neo-blessed');
const Hyperswarm = require('hyperswarm') const Hyperswarm = require('hyperswarm')
const crypto = require('hypercore-crypto') const crypto = require('hypercore-crypto')
const b4a = require('b4a') const b4a = require('b4a')
const readline = require('readline') const readline = require('readline')
const fs = require("fs"); const fs = require("fs");
// Import our command // Import our commands - You must add this line.
// Otherwise there is no access to the command functions
const { login } = require('./commands/login'); const { login } = require('./commands/login');
const { execute } = require('./commands/exec'); const { execute } = require('./commands/exec');
const { stop } = require('./commands/stop'); const { stop } = require('./commands/stop');
@ -16,41 +17,76 @@ const { stats } = require('./commands/stats');
const { changeDir } = require('./commands/cd'); const { changeDir } = require('./commands/cd');
const { AIRequest } = require('./commands/AI'); const { AIRequest } = require('./commands/AI');
// Generate a random number, this is used when generating a anon name
let rand = Math.floor(Math.random() * 99999).toString(); let rand = Math.floor(Math.random() * 99999).toString();
// Storage for our clients information
let USERPWD = "/" let USERPWD = "/"
let DAPI_KEY let DAPI_KEY
let LOGGEDIN = false let LOGGEDIN = false
let MYKEY = [] let MYKEY = []
let conns = [] let conns = []
let connectedUsers = []; let connectedUsers = [];
let USERNAME = ["annon" + rand] let USERNAME = ["anon" + rand]
let DISCORD_USERID = []
// Sleep function used when closing connections.
function sleep(ms) { function sleep(ms) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, ms); setTimeout(resolve, ms);
}); });
} }
// Adding a user to a peer and user MAP to keep track of peers.
function addUser(user, peerId) { function addUser(user, peerId) {
connectedUsers.push({ name: user, peerId: peerId }); connectedUsers.push({ name: user, peerId: peerId });
sidebarBox.setContent(connectedUsers.map(user => `${user.name} - ${user.peerId}`).join("\n")); sidebarBox.setContent(connectedUsers.map(user => `${user.peerId}`).join("\n"));
screen.render(); screen.render();
} }
// Removing a user to a peer and user MAP to keep track of peers.
// TODO: Get this to work properly
function removeUser(peerId) { function removeUser(peerId) {
connectedUsers = connectedUsers.filter(user => user.peerId !== peerId); connectedUsers = connectedUsers.filter(user => user.peerId !== peerId);
sidebarBox.setContent("Connected Peers: \n" + connectedUsers.map(user => `${user.name} - ${user.peerId}`).join("\n")); sidebarBox.setContent("Peers since connection: \n" + connectedUsers.map(user => `${user.peerId}`).join("\n"));
screen.render(); screen.render();
} }
// Create the screen // Create the screen for blessed
const screen = blessed.screen({ const screen = blessed.screen({
smartCSR: true, smartCSR: true,
fastCSR: true fastCSR: true
}); });
// Quit on Escape, q, or Control-C.
screen.key(['escape', 'q', 'C-c'], function (ch, key) {
console.log("Sending close message...")
for (let conn of conns) {
conn.write(`CLOSED: ${publicKey.toString('hex')}`)
}
(async () => {
await sleep(2000)
process.exit()
})();
});
// When users press ESC, you may press t or enter to go back
// to the chat input box
screen.key(['t', 'enter'], function (ch, key) {
stdinBox.focus();
});
// When users press ESC, you may press p to go to the mainbox
// This lets users scroll the chat feed.
screen.key(['p'], function (ch, key) {
sidebarBox.focus();
});
// Debug ONLY - Use this to capture keypress events
// screen.on('keypress', function(ch, key){
// console.log(JSON.stringify(key));
// });
// Creating the mainbox
let mainBox = blessed.box({ let mainBox = blessed.box({
parent: screen, parent: screen,
top: 0, top: 0,
@ -75,6 +111,7 @@ let mainBox = blessed.box({
} }
}); });
// A function to update the mainbox scroll per message.
async function updateScroll() { async function updateScroll() {
mainBox.scrollTo(mainBox.getScrollHeight()); mainBox.scrollTo(mainBox.getScrollHeight());
@ -100,49 +137,59 @@ const stdinBox = blessed.textbox({
input: true input: true
}); });
// Create the sidebar box for connected peers
const sidebarBox = blessed.box({ // Sidebar to display all peers that have been seen
let sidebarBox = blessed.box({
parent: screen,
top: '0', top: '0',
right: '0', right: '0',
width: '20%', width: '20%',
height: '100%', height: '100%',
content: '',
border: { border: {
type: 'line' type: 'line'
}, },
style: { style: {
fg: 'white', fg: 'white',
bg: 'black', bg: 'black'
border: { },
fg: '#f0f0f0' keys: true,
}, vi: true,
alwaysScroll: true,
scrollable: true,
scrollbar: {
style: {
bg: 'yellow'
}
} }
}); });
// Setting the sidebar label.
sidebarBox.setLabel("Peers since connection: 0") sidebarBox.setLabel("Peers since connection: 0")
// Replacing the console.log function with our own
// This sends all console.log events to the main window.
const originalLog = console.log; const originalLog = console.log;
console.log = (...args) => { console.log = (...args) => {
mainBox.setContent(mainBox.getContent() + `\n${args.join(' ')}`); mainBox.setContent(mainBox.getContent() + `\n${args.join(' ')}`);
updateScroll() updateScroll()
stdinBox.clearValue(); stdinBox.clearValue();
screen.render() screen.render()
} }
// Generate a random public key // Generate a random public key
const publicKey = crypto.randomBytes(32) const publicKey = crypto.randomBytes(32)
// Create the swarm and pass in the public key // Create the swarm and pass in the public key
const swarm = new Hyperswarm() const swarm = new Hyperswarm()
const commandDir = './commands/'; // Set up our commands
const commandDir = __dirname + '/commands/';
const commandFiles = fs.readdirSync(commandDir); const commandFiles = fs.readdirSync(commandDir);
const commands = {} const commands = {}
// For each command lets add it to a var
for (const file of commandFiles) { for (const file of commandFiles) {
const commandName = file.split(".")[0] const commandName = file.split(".")[0]
require(`${commandDir}/${file}`) require(`${commandDir}/${file}`)
@ -151,6 +198,7 @@ for (const file of commandFiles) {
} }
// The command handler
async function handleCommand(input) { async function handleCommand(input) {
if (input.startsWith("!") || input.startsWith(">")) { if (input.startsWith("!") || input.startsWith(">")) {
const command = input.split(" ") const command = input.split(" ")
@ -167,7 +215,7 @@ async function handleCommand(input) {
stats(MYKEY[0]) stats(MYKEY[0])
break; break;
case ">": case ">":
execute(MYKEY[0], command.slice(1).join(" "), USERPWD, conns); execute(MYKEY[0], command.slice(1).join(" "), USERPWD, conns, USERNAME);
break; break;
case ">restart": case ">restart":
restart(MYKEY[0]) restart(MYKEY[0])
@ -179,7 +227,7 @@ async function handleCommand(input) {
start(MYKEY[0]) start(MYKEY[0])
break; break;
case ">login": case ">login":
login(command[1], conns, MYKEY, USERNAME) login(command[1], conns, MYKEY, USERNAME, DISCORD_USERID)
break; break;
case ">exit": case ">exit":
console.log("Sending close message...") console.log("Sending close message...")
@ -194,12 +242,19 @@ async function handleCommand(input) {
console.log("Command not found.") console.log("Command not found.")
} }
} else { } else {
for (const conn of conns) if (DISCORD_USERID.length !== 0) {
for (const conn of conns)
conn.write(`${USERNAME[0]}: ${input}`) conn.write(`${DISCORD_USERID[0]}: ${input}`)
} else {
for (const conn of conns)
conn.write(`${USERNAME}: ${input}`)
}
if (DISCORD_USERID.length !== 0) {
console.log(`${DISCORD_USERID[0]}: ${input}`)
} else {
console.log(`${USERNAME}: ${input}`)
}
} }
console.log(`${USERNAME[0]}: ${input}`)
} }
swarm.on('connection', conn => { swarm.on('connection', conn => {
@ -215,27 +270,38 @@ swarm.on('connection', conn => {
}) })
// Remote Connection Name
const name = b4a.toString(conn.remotePublicKey, 'hex') const name = b4a.toString(conn.remotePublicKey, 'hex')
console.log(`* got a connection from ${name} (${USERNAME[0]}) *`) console.log(`* got a connection from ${name} (${USERNAME[0]}) *`)
// Add the user to the MAP
addUser(USERNAME[0], name) addUser(USERNAME[0], name)
sidebarBox.setLabel("Connected Peers: " + connectedUsers.length) // Update the sidebar
sidebarBox.setLabel("Peers since connection: " + connectedUsers.length)
// Render the changes
screen.render() screen.render()
// Add the connection to the conn list
conns.push(conn) conns.push(conn)
// IF the connection is closed, remove a connection
conn.once('close', () => conns.splice(conns.indexOf(conn), 1)) conn.once('close', () => conns.splice(conns.indexOf(conn), 1))
// Handle data as it comes in from the peer stream
conn.on('data', data => { conn.on('data', data => {
// If data shows that a peer has left, lets handle it and remove their key
if (data.toString().startsWith('CLOSED:')) { if (data.toString().startsWith('CLOSED:')) {
// Extract the key from the message string // Extract the key from the message string
const key = data.toString().split(':')[1].trim(); const key = data.toString().split(':')[1].trim();
removeUser(key) removeUser(key)
console.log(`Removing peer ${key}`); console.log(`Removing peer ${key}`);
(async () => {
// Wait 5 seconds, remove the peer from the connections
// This stops timeouts which crashes all peers.
(async () => {
await sleep(5000) await sleep(5000)
conns = conns.filter(c => c !== conn); conns = conns.filter(c => c !== conn);
conn.destroy(); conn.destroy();
})(); })();
} else { } else {
// If there is no actions detected, update chat.
console.log(`${data}`) console.log(`${data}`)
} }
// Use the USERNAME if it has been set, otherwise use the public key // Use the USERNAME if it has been set, otherwise use the public key
@ -246,11 +312,10 @@ swarm.on('error', (err) => {
console.log('Error connecting to peer:', err); console.log('Error connecting to peer:', err);
}); });
// Join a common topic // Join a common topic
const topic = process.argv[2] ? b4a.from(process.argv[2], 'hex') : crypto.randomBytes(32) const topic = process.argv[2] ? b4a.from(process.argv[2], 'hex') : crypto.randomBytes(32)
// Join the topic with a timeout
setTimeout(() => { setTimeout(() => {
const discovery = swarm.join(topic, { const discovery = swarm.join(topic, {
lookup: true, lookup: true,
@ -267,15 +332,11 @@ setTimeout(() => {
}) })
}, 1000); }, 1000);
// Append the boxes to the screen // Append the boxes to the screen
screen.append(mainBox); screen.append(mainBox);
screen.append(stdinBox); screen.append(stdinBox);
screen.append(sidebarBox); screen.append(sidebarBox);
// Handle input in the stdinBox // Handle input in the stdinBox
stdinBox.on('submit', (input) => { stdinBox.on('submit', (input) => {
// handle the input here // handle the input here
@ -283,19 +344,8 @@ stdinBox.on('submit', (input) => {
handleCommand(input); handleCommand(input);
// clear the input field // clear the input field
stdinBox.focus(); stdinBox.focus();
// screen.render();
}); });
// setInterval(() => {
// mainBox.scrollTo(mainBox.getScrollHeight());
// }, 1000);
stdinBox.focus(); stdinBox.focus();
// Render the screen // Render the screen
screen.render() screen.render()
// Quit on Escape, q, or Control-C.
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});