pipebomb.js
Version:
Library for interacting with Pipe Bomb servers
147 lines • 5.88 kB
JavaScript
import Axios from "axios";
import CollectionCache from "./collection/CollectionCache.js";
import Context from "./Context.js";
import TrackCache from "./music/TrackCache.js";
import V1 from "./version/V1.js";
import Cryptico from "./Crypto.js";
import CryptoJS from "crypto-js";
import { BufferShim } from "./lib/Buffer.js";
export default class PipeBomb {
constructor(serverURL, options) {
this.context = new Context(serverURL, this, options);
this.trackCache = new TrackCache(this.context, options?.trackCacheTime ?? 60);
this.collectionCache = new CollectionCache(this.context, this.trackCache, options?.CollectionCacheTime ?? 600);
this.v1 = new V1(this.context, this.trackCache, this.collectionCache);
}
async authenticate(username, options) {
let privateKey = options?.privateKey;
if (privateKey) {
this.context.setPrivateKey(options.privateKey);
}
else {
privateKey = this.context.getPrivateKey();
if (!privateKey) {
throw `Pipe Bomb instance has not been assigned a private key`;
}
}
this.context.setUsername(username);
const key = Cryptico.RSAKey.parse(BufferShim.from(privateKey, "base64").toString("utf-8"));
const publicKey = Cryptico.publicKeyString(key);
const userID = PipeBomb.getUserIDFromPublicKey(publicKey);
this.context.setPrivateKey(privateKey);
const response = await this.context.makeRequest("post", "v1/login", {
user_id: userID,
public_key: publicKey,
create_if_missing: !!options?.createIfMissing
});
if (response.statusCode != 200 || typeof response.response?.secret != "string")
throw response;
const secret = response.response.secret;
const decrypted = PipeBomb.decrypt(secret, privateKey);
const tokenResponse = await this.context.makeRequest("post", "v1/authenticate", {
user_id: userID,
username,
secret: decrypted
});
if (tokenResponse.statusCode != 200 || typeof tokenResponse.response?.token != "string")
throw tokenResponse;
const token = tokenResponse.response.token;
this.context.setToken(token);
return token;
}
static async checkHost(serverURL) {
if (serverURL.toLowerCase().startsWith("http://")) {
serverURL = serverURL.substring(7);
}
else if (serverURL.toLowerCase().startsWith("https://")) {
serverURL = serverURL.substring(8);
}
while (serverURL.endsWith("/")) {
serverURL = serverURL.slice(0, -1);
}
function connect(https) {
return new Promise(async (resolve, reject) => {
Axios.get(`http${https ? "s" : ""}://${serverURL}/v1/identify`)
.then(data => {
if (data.data?.statusCode == 200 && data.data?.response?.pipeBombServer === true || typeof data.data?.response?.name === "string") {
return resolve(data.data.response.name);
}
reject("not pipe bomb");
}, () => {
reject("connection failure");
});
});
}
try {
const name = await connect(true);
return {
host: "https://" + serverURL,
name,
https: true
};
}
catch (e) {
if (e == "not pipe bomb") {
return null;
}
}
try {
const name = await connect(false);
return {
host: "http://" + serverURL,
name,
https: false
};
}
catch { }
return null;
}
static getCredentialHash(username, password) {
const passwordHash = CryptoJS.SHA256(password).toString();
const usernameHash = CryptoJS.SHA256(username).toString();
const hash = CryptoJS.SHA256(passwordHash + usernameHash).toString();
return hash;
}
static getUserIDFromPublicKey(publicKey) {
return Cryptico.publicKeyID(publicKey);
}
static generatePrivateKey(accountHash) {
const privateKeyJson = Cryptico.generateRSAKey(accountHash, 2048);
const privateKey = BufferShim.from(JSON.stringify(privateKeyJson.toJSON())).toString("base64");
return privateKey;
}
static getAccountKeys(privateKey) {
const privateKeyJson = Cryptico.RSAKey.parse(BufferShim.from(privateKey, "base64").toString("utf-8"));
const publicKey = Cryptico.publicKeyString(privateKeyJson);
return {
publicKey,
userID: this.getUserIDFromPublicKey(publicKey)
};
}
static encrypt(message, publicKey) {
try {
if (typeof message == "object") {
message = JSON.stringify(message);
}
}
catch { }
const response = Cryptico.encrypt(message, publicKey);
if (response.status != "success")
throw `Failed to encrypt payload with public key`;
return response.cipher;
}
static decrypt(message, privateKey) {
const key = Cryptico.RSAKey.parse(BufferShim.from(privateKey, "base64").toString("utf-8"));
const response = Cryptico.decrypt(JSON.stringify(message), key);
if (response.status != "success")
throw `Failed to decrypt payload with private key`;
try {
if (response.plaintext.startsWith("[") || response.plaintext.startsWith("{")) {
return JSON.parse(response.plaintext);
}
}
catch { }
return response.plaintext;
}
}
//# sourceMappingURL=index.js.map