Spaces:
Build error
Build error
const BlockType = require('../../extension-support/block-type'); | |
const ArgumentType = require('../../extension-support/argument-type'); | |
const Cast = require('../../util/cast'); | |
const uid = require('../../util/uid'); | |
/** | |
* Class for storage blocks | |
* @constructor | |
*/ | |
class JgStorageBlocks { | |
constructor(runtime) { | |
/** | |
* The runtime instantiating this block package. | |
* @type {Runtime} | |
*/ | |
this.runtime = runtime; | |
this.currentServer = "https://storage-ext.penguinmod.com/"; | |
this.usePenguinMod = true; | |
this.useGlobal = true; | |
this.waitingForResponse = false; | |
this.serverFailedResponse = false; | |
this.serverError = ""; | |
this.uniquePrefix = "u" + uid(); | |
// A value stored in the PMP of the project. | |
// This value should always be globally unique to | |
// every project. | |
// The chance that 2 projects have the same "unique" | |
// prefix is about very small. | |
// The u at the start is to make sure that it can never | |
// be mistaken for a project id. | |
} | |
/** | |
* @returns {object} metadata for this extension and its blocks. | |
*/ | |
getInfo() { | |
return { | |
id: 'jgStorage', | |
name: 'Storage', | |
color1: '#76A8FE', | |
color2: '#538EFC', | |
docsURI: 'https://docs.penguinmod.com/extensions/storage', | |
blocks: [ | |
{ | |
blockType: BlockType.LABEL, | |
text: "Local Storage" | |
}, | |
{ | |
opcode: 'getValue', | |
text: 'get [KEY]', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
} | |
}, | |
{ | |
opcode: 'setValue', | |
text: 'set [KEY] to [VALUE]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: "value" | |
}, | |
} | |
}, | |
{ | |
opcode: 'deleteValue', | |
text: 'delete [KEY]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
} | |
} | |
}, | |
{ | |
opcode: 'getKeys', | |
text: 'get all stored names', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER | |
}, | |
{ | |
blockType: BlockType.LABEL, | |
text: "Local Uploaded Project Storage" | |
}, | |
{ | |
opcode: 'getProjectValue', | |
text: 'get uploaded project [KEY]', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
} | |
}, | |
{ | |
opcode: 'setProjectValue', | |
text: 'set uploaded project [KEY] to [VALUE]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: "value" | |
}, | |
} | |
}, | |
{ | |
opcode: 'deleteProjectValue', | |
text: 'delete uploaded project [KEY]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
} | |
} | |
}, | |
{ | |
opcode: 'getProjectKeys', | |
text: 'get all stored names in this uploaded project', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER | |
}, | |
{ | |
blockType: BlockType.LABEL, | |
text: "Local Project Storage" | |
}, | |
{ | |
opcode: 'getUniqueValue', | |
text: 'get local project [KEY]', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
} | |
}, | |
{ | |
opcode: 'setUniqueValue', | |
text: 'set local project [KEY] to [VALUE]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: "value" | |
}, | |
} | |
}, | |
{ | |
opcode: 'deleteUniqueValue', | |
text: 'delete local project [KEY]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
} | |
} | |
}, | |
{ | |
opcode: 'getUniqueKeys', | |
text: 'get all stored names in this local project', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER | |
}, | |
{ | |
blockType: BlockType.LABEL, | |
text: "Server Storage" | |
}, | |
{ | |
opcode: 'isGlobalServer', | |
text: 'is using global server?', | |
disableMonitor: true, | |
blockType: BlockType.BOOLEAN | |
}, | |
{ | |
opcode: 'useCertainServer', | |
text: 'set server to [SERVER] server', | |
disableMonitor: true, | |
blockType: BlockType.COMMAND, | |
arguments: { | |
SERVER: { | |
type: ArgumentType.STRING, | |
menu: "serverType" | |
}, | |
} | |
}, | |
{ | |
opcode: 'waitingForConnection', | |
text: 'waiting for server to respond?', | |
disableMonitor: true, | |
blockType: BlockType.BOOLEAN | |
}, | |
{ | |
opcode: 'connectionFailed', | |
text: 'server failed to respond?', | |
disableMonitor: true, | |
blockType: BlockType.BOOLEAN | |
}, | |
{ | |
opcode: 'serverErrorOutput', | |
text: 'server error', | |
disableMonitor: false, | |
blockType: BlockType.REPORTER | |
}, | |
"---", | |
{ | |
opcode: 'getServerValue', | |
text: 'get server [KEY]', | |
disableMonitor: true, | |
blockType: BlockType.REPORTER, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
} | |
}, | |
{ | |
opcode: 'setServerValue', | |
text: 'set server [KEY] to [VALUE]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
}, | |
VALUE: { | |
type: ArgumentType.STRING, | |
defaultValue: "value" | |
}, | |
} | |
}, | |
{ | |
opcode: 'deleteServerValue', | |
text: 'delete server [KEY]', | |
blockType: BlockType.COMMAND, | |
arguments: { | |
KEY: { | |
type: ArgumentType.STRING, | |
defaultValue: "key" | |
} | |
} | |
} | |
], | |
menus: { | |
serverType: { | |
acceptReporters: true, | |
items: [ | |
"project", | |
"global" | |
].map(item => ({ text: item, value: item })) | |
} | |
} | |
}; | |
} | |
// Storage | |
serialize() { | |
return { uniqueId: this.uniquePrefix } | |
} | |
deserialize(data) { | |
this.uniquePrefix = data.uniqueId; | |
} | |
// utilities | |
/** | |
* @returns {string} Prefix for any keys saved | |
*/ | |
getPrefix(projectId) { | |
return `PM_PROJECTSTORAGE_EXT_${projectId == null ? "" : `${projectId}_`}`; | |
} | |
getAllKeys(projectId) { | |
return Object.keys(localStorage).filter(key => key.startsWith(this.getPrefix(projectId))).map(key => key.replace(this.getPrefix(projectId), "")); | |
} | |
getProjectId() { | |
/* todo: get the project id in a like 190x better way lol */ | |
const hash = String(window.location.hash).replace(/#/gmi, ""); | |
return Cast.toNumber(hash); | |
} | |
runPenguinWebRequest(url, options, ifFailReturn) { | |
this.waitingForResponse = true; | |
this.serverFailedResponse = false; | |
this.serverError = ""; | |
return new Promise((resolve) => { | |
let promise = null; | |
if (options !== null) { | |
promise = fetch(url, options); | |
} else { | |
promise = fetch(url); | |
} | |
promise.then(response => { | |
response.text().then(text => { | |
if (!response.ok) { | |
this.waitingForResponse = false; | |
this.serverFailedResponse = true; | |
this.serverError = Cast.toString(text); | |
if (ifFailReturn !== null) { | |
return resolve(ifFailReturn); | |
} | |
resolve(text); | |
return; | |
} | |
this.waitingForResponse = false; | |
this.serverFailedResponse = false; | |
this.serverError = ""; | |
resolve(text); | |
}).catch(err => { | |
this.waitingForResponse = false; | |
this.serverFailedResponse = true; | |
this.serverError = Cast.toString(err); | |
if (ifFailReturn !== null) { | |
return resolve(ifFailReturn); | |
} | |
resolve(err); | |
}) | |
}).catch(err => { | |
this.waitingForResponse = false; | |
this.serverFailedResponse = true; | |
this.serverError = Cast.toString(err); | |
if (ifFailReturn !== null) { | |
return resolve(ifFailReturn); | |
} | |
resolve(err); | |
}) | |
}) | |
} | |
getCurrentServer() { | |
return `https://storage-ext.penguinmod.com/` | |
} | |
// blocks | |
getKeys() { | |
return JSON.stringify(this.getAllKeys()); | |
} | |
getValue(args) { | |
const key = this.getPrefix() + Cast.toString(args.KEY); | |
const returned = localStorage.getItem(key); | |
if (returned === null) return ""; | |
return Cast.toString(returned); | |
} | |
setValue(args) { | |
const key = this.getPrefix() + Cast.toString(args.KEY); | |
const value = Cast.toString(args.VALUE); | |
return localStorage.setItem(key, value); | |
} | |
deleteValue(args) { | |
const key = this.getPrefix() + Cast.toString(args.KEY); | |
return localStorage.removeItem(key); | |
} | |
// project blocks | |
getProjectKeys() { | |
return JSON.stringify(this.getAllKeys(this.getProjectId())); | |
} | |
getProjectValue(args) { | |
const key = this.getPrefix(this.getProjectId()) + Cast.toString(args.KEY); | |
const returned = localStorage.getItem(key); | |
if (returned === null) return ""; | |
return Cast.toString(returned); | |
} | |
setProjectValue(args) { | |
const key = this.getPrefix(this.getProjectId()) + Cast.toString(args.KEY); | |
const value = Cast.toString(args.VALUE); | |
return localStorage.setItem(key, value); | |
} | |
deleteProjectValue(args) { | |
const key = this.getPrefix(this.getProjectId()) + Cast.toString(args.KEY); | |
return localStorage.removeItem(key); | |
} | |
// global unique blocks | |
getUniqueKeys() { | |
return JSON.stringify(this.getAllKeys(this.uniquePrefix)); | |
} | |
getUniqueValue(args) { | |
const key = this.getPrefix(this.uniquePrefix) + Cast.toString(args.KEY); | |
const returned = localStorage.getItem(key); | |
if (returned === null) return ""; | |
return Cast.toString(returned); | |
} | |
setUniqueValue(args) { | |
const key = this.getPrefix(this.uniquePrefix) + Cast.toString(args.KEY); | |
const value = Cast.toString(args.VALUE); | |
return localStorage.setItem(key, value); | |
} | |
deleteUniqueValue(args) { | |
const key = this.getPrefix(this.uniquePrefix) + Cast.toString(args.KEY); | |
return localStorage.removeItem(key); | |
} | |
// server blocks | |
isGlobalServer() { | |
return this.useGlobal; | |
} | |
useCertainServer(args) { | |
const serverType = Cast.toString(args.SERVER).toLowerCase(); | |
if (["project", "global"].includes(serverType)) { | |
// this is a menu option | |
this.currentServer = "https://storage-ext.penguinmod.com/"; | |
this.usePenguinMod = true; | |
this.useGlobal = serverType === "global"; | |
} else { | |
// this is a url | |
this.currentServer = Cast.toString(args.SERVER); | |
if (!this.currentServer.endsWith("/")) { | |
this.currentServer += "/"; | |
} | |
this.usePenguinMod = false; | |
this.useGlobal = true; | |
} | |
// now lets wait until the server responds saying it is online | |
return this.runPenguinWebRequest(this.currentServer); | |
} | |
waitingForConnection() { | |
return this.waitingForResponse; | |
} | |
connectionFailed() { | |
return this.serverFailedResponse; | |
} | |
serverErrorOutput() { | |
return this.serverError; | |
} | |
getServerValue(args) { | |
const key = Cast.toString(args.KEY); | |
return this.runPenguinWebRequest(`${this.currentServer}get?key=${key}${this.useGlobal ? "" : `&project=${this.getProjectId()}`}`, null, ""); | |
} | |
setServerValue(args) { | |
const key = Cast.toString(args.KEY); | |
const value = Cast.toString(args.VALUE); | |
return this.runPenguinWebRequest(`${this.currentServer}set?key=${key}${this.useGlobal ? "" : `&project=${this.getProjectId()}`}`, { | |
method: "POST", | |
headers: { "Content-Type": "application/json" }, | |
body: JSON.stringify({ | |
"value": value | |
}) | |
}); | |
} | |
deleteServerValue(args) { | |
const key = Cast.toString(args.KEY); | |
return this.runPenguinWebRequest(`${this.currentServer}delete?key=${key}${this.useGlobal ? "" : `&project=${this.getProjectId()}`}`, { | |
method: "DELETE" | |
}); | |
} | |
} | |
module.exports = JgStorageBlocks; | |