From 1e92cd541dfe32662a59f677676af1c02a219cca Mon Sep 17 00:00:00 2001 From: hiimgoodpack Date: Thu, 31 Dec 2020 12:22:07 -0500 Subject: [PATCH] Initialize project --- .gitmodules | 3 + README.md | 17 +++- brainlet-lib | 1 + index.js | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 18 ++++ 5 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 160000 brainlet-lib create mode 100644 index.js create mode 100644 package.json diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2f6ff2c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "brainlet-lib"] + path = brainlet-lib + url = https://git.hippoz.xyz/hiimgoodpack/brainlet-lib.git diff --git a/README.md b/README.md index 6b3b3a5..3f178bc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ # brainlet-cli -a better frontend for brainlet \ No newline at end of file +a better (unofficial) frontend for brainlet + +# Installation +``` +git clone --depth=1 --recurse-submodules https://git.hippoz.xyz/hiimgoodpack/brainlet-cli.git +cd brainlet-cli +pushd brainlet-lib +npm install +popd +npm install +``` + +# Usage +``` +node index.js +``` diff --git a/brainlet-lib b/brainlet-lib new file mode 160000 index 0000000..b3d9f22 --- /dev/null +++ b/brainlet-lib @@ -0,0 +1 @@ +Subproject commit b3d9f220b0941c088060c867135ff804d10fad77 diff --git a/index.js b/index.js new file mode 100644 index 0000000..eb4f788 --- /dev/null +++ b/index.js @@ -0,0 +1,261 @@ +/* + Unofficial brainlet command-line interface + Copyright (C) 2020 hiimgoodpack + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +const brainlet = require("./brainlet-lib/index.js"); +const readline = require("readline").createInterface({ + input: process.stdin, + output: process.stdout +}); + +const ask = (question) => { + return new Promise((res, rej) => { + readline.question(question, res); + }); +}; + +const catchErrors = (promise) => { + return new Promise((res, rej) => { + promise.then(res).catch((...errors) => { + console.error(...errors); + res(undefined); + }); + }); +}; + +const promiseSucceeded = async (promise) => { + return await new Promise((res, rej) => { + promise.then(() => { + res(true); + }).catch((...errors) => { + console.error(...errors); + res(false); + }); + }); +}; + +const getColorCode = ([r, g, b]) => { + return `\x1b[38;2;${r};${g};${b}m`; +}; +const resetColorCode = "\x1b[0m"; +const clearLine = "\x1b[2K"; + +const hexToRGB = (hex) => { + let decimal = parseInt(hex.substr(1), 16); + return [(decimal & 0xFF0000) >> 16, (decimal & 0xFF00) >> 8, decimal & 0xFF]; +}; + +let user = {}; + +console.log(`Unofficial brainlet command-line interface +Copyright (C) 2020 hiimgoodpack +License GPLv3+: GNU GPL version 3 or later + +Warning: You should not connect to an untrusted server, +or a server with untrusted clients, as there may be some risks +with outputting arbritrary text ot the console. +`); + +// Put in async function +(async() => { + const server = process.argv[2]; + let prompt = 1; + let developerMode = 0; + let socket; + + const useDeveloperMode = () => { + return new Promise((res, rej) => { + if (!developerMode) { + ask(`Warning: This command requires developer mode to be enabled. +Enabling developer mode may enable commands which can reveal private information or information +which can be used to log into your account. + +Note: Every time the client is started, developer mode is disabled, even if you have enabled it previously in another session. + +Are you sure you want to enable developer mode? [y/n] `).then((response) => { + if (response === "y") { + developerMode = true; + console.log("Developer mode has been enabled") + } + res(); + }); + } else + res(); + }); + } + + while (prompt) { + const input = await ask("> "); + switch (input) { + case "q": + case "quit": { + prompt = 0; + break; + } + + case "signup": { + let newUser = {}; + + // Get username, email, and password + while (1) { + newUser.name = await ask("Username: "); + + let error = brainlet.valid.username(newUser.name); + if (error) + console.error(error); + else + break; + } + while (1) { + newUser.email = await ask("Email: "); + + let error = brainlet.valid.email(newUser.email); + if (error) + console.error(error); + else + break; + } + while (1) { + newUser.password = await ask("Password: "); + + let error = brainlet.valid.password(newUser.password); + if (error) + console.error(error); + else + break; + } + while (1) { + let confirmationPassword = await ask("Enter same password again: "); + if (confirmationPassword === newUser.password) + break; + else + console.error("Passwords do not match"); + } + + if (await promiseSucceeded(brainlet.users.create(server, newUser))) { + console.log("Account successfully created. To log in, use the \"login\" command"); + } + + break; + } + + case "login": { + // Get username and password + while (1) { + user.name = await ask("Username: "); + + let error = brainlet.valid.username(user.name); + if (error) + console.error(error); + else + break; + } + while (1) { + user.password = await ask("Password: "); + + let error = brainlet.valid.password(user.password); + if (error) + console.error(error); + else + break; + } + + let newUser = await catchErrors(brainlet.users.login(server, user)); + + if (newUser) { + newUser.password = undefined; + newUser.email = undefined; + + user = newUser; + console.log("Successfully logged in, starting connection"); + + socket = await brainlet.categories.client(server, user.token); + console.log("Connection started"); + } + break; + } + + case "ls": { + if (!socket) { + console.error("You must log in before listing categories"); + break; + } + const limit = 5; + let categories = await catchErrors(brainlet.categories.list(server, user.token, limit)); + + if (categories) { + if (categories === limit) { + console.error(`Warning: This may be an incomplete list of categories`); + } + console.log("CATEGORY ID | CATEGORY TITLE"); + for (let category of categories) { + console.log(`${category._id} | ${category.title}`); + } + } + break; + } + + case "join": { + if (!socket) { + console.error("You must log in before joining a category"); + break; + } + let categoryID = await ask("Category ID: "); + await catchErrors(socket.connect([categoryID])); + console.log(`Successfully joined category ${categoryID}. +Anything typed will be sent to other users, unless it is prefixed with '/'. +To leave this category, use '/quit'`); + + const PS1 = `${getColorCode(hexToRGB(user.color))}${user.name}${resetColorCode} [message currently not sent]: `; + socket.onMessage((message) => { + if (message.category._id === categoryID) { + process.stdout.write(`\r${clearLine}${getColorCode(hexToRGB(message.author.color))}${message.author.username}${resetColorCode}: ${message.content}\n${PS1}`); + } + }); + let sendMessages = true; + while (sendMessages) { + const message = await ask(PS1); + switch (message) { + case "/leave": { + sendMessages = false; + break; + } + + default: { + if (message[0] === "/") { + console.error(`${getColorCode([0xdd, 0, 0])}Invalid command ${message}`); + break; + } + + socket.send(categoryID, message); + } + } + } + break; + } + + case "dump": { + await useDeveloperMode(); + if (developerMode) { + console.log(user); + } + break; + } + } + } + readline.close(); +})(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..962707a --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "brainlet-cli", + "version": "1.0.0", + "description": "a better (unofficial) frontend for brainlet", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://git.hippoz.xyz/hiimgoodpack/brainlet-cli.git" + }, + "author": "", + "license": "GPL-3.0-or-later", + "dependencies": { + "readline": "^1.3.0" + } +}