diff --git a/AABrowserAPI/API.js b/AABrowserAPI/API.js new file mode 100644 index 000000000..67a3b3660 --- /dev/null +++ b/AABrowserAPI/API.js @@ -0,0 +1,128 @@ +exports.newAPI = function newAPI() { + + let thisObject = { + saveBotCode: saveBotCode, + initialize: initialize + } + + let serverConfig; + + return thisObject; + + function initialize(pServerConfig) { + + serverConfig = pServerConfig; + + } + + function saveBotCode(pSourceCode, callBackFunction) { + + writeData("AAMasters", "AAMariam-Trading-Bot", "Trading-Process/User.Bot.js", pSourceCode, onDataWritten); + + function onDataWritten(err) { + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + console.log("[ERROR] API -> saveBotCode -> Source code file could not be saved. "); + console.log("[ERROR] API -> saveBotCode -> err.message = " + err.message); + + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + } + } + + function writeData(pOrg, pRepo, pPath, pFileContent, callBackFunction) { + + try { + + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> Entering function."); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> pOrg = " + pOrg); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> pRepo = " + pRepo); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> pPath = " + pPath); } + + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> " + pOrg + '.' + pRepo + '.' + pPath + " NOT found at cache."); } + + let storage = require('azure-storage'); + let connectionString; + + switch (serverConfig.environment) { + + case "Develop": { + + connectionString = serverConfig.configAndPlugins.Develop.connectionString; + break; + } + + case "Production": { + + connectionString = serverConfig.configAndPlugins.Production.connectionString; + break; + } + } + + let blobService = storage.createBlobService(connectionString); + let blobPath = pOrg + "/" + pRepo + "/" + pPath; + let blobText = nodeify(pFileContent.toString()); + + blobService.createBlockBlobFromText('aaplatform', blobPath, blobText, onFileReceived); + + function onFileReceived(err, text, response) { + + try { + + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> onFileReceived -> Entering function."); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> onFileReceived -> err = " + JSON.stringify(err)); } + if (LOG_FILE_CONTENT === true) { console.log("[INFO] API -> writeData -> onFileReceived -> response = " + JSON.stringify(response)); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> onFileReceived -> pOrg = " + pOrg); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> onFileReceived -> pRepo = " + pRepo); } + if (CONSOLE_LOG === true) { console.log("[INFO] API -> writeData -> onFileReceived -> pPath = " + pPath); } + + if (err !== null || text === null) { + + if (CONSOLE_LOG === true) { console.log("[ERROR] API -> writeData -> onFileReceived -> Error Received from API Library. "); } + if (CONSOLE_LOG === true) { console.log("[ERROR] API -> writeData -> onFileReceived -> err = " + JSON.stringify(err)); } + if (CONSOLE_LOG === true) { console.log("[ERROR] API -> writeData -> onFileReceived -> Returning an empty JSON object string. "); } + + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + + } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } catch (err) { + console.log("[ERROR] API -> writeData -> onFileReceived -> err.message = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + } catch (err) { + console.log("[ERROR] API -> writeData -> err.message = " + err.message); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function nodeify(pData) { + + + let start = pData.indexOf('function') + 9; + let end = pData.indexOf('(') + 0; + + let functionName = pData.substring(start, end); + + let result = "exports." + functionName + " = " + pData; + + result = replaceAll(result, "webRequire", "require"); + result = replaceAll(result, "window", "global"); + + return result; + + function replaceAll(text, search, replacement) { + return text.replace(new RegExp(search, 'g'), replacement); + } + } + +} \ No newline at end of file diff --git a/CloudVM/CloudSupport.js b/CloudVM/CloudSupport.js index bd9f9cbfe..691074e3b 100644 --- a/CloudVM/CloudSupport.js +++ b/CloudVM/CloudSupport.js @@ -9,28 +9,7 @@ When running at the clode on NodeJS some things work diffently that at the brows -function onBotPlayPressed(pUI_COMMANDS) { - window.SHALL_BOT_STOP = false; - - window.CURRENT_ENVIRONMENT = "Develop"; - window.STORAGE_PERMISSIONS = ecosystem.getStoragePermissions(); - window.EXCHANGE_KEYS = ecosystem.getExchangeKeys(); - - cloudVM.initialize(pUI_COMMANDS, onInitialized); - - function onInitialized() { - - cloudVM.start(); - } - -} - -function onBotStopPressed() { - - window.SHALL_BOT_STOP = true; - -} function webRequire(pModulePath) { @@ -162,7 +141,7 @@ function downloadModule(pPath, callBackFunction) { } } -function callServer(pPath, callBackFunction) { +function callServer(pContentToSend, pPath, callBackFunction) { let xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { @@ -172,9 +151,20 @@ function callServer(pPath, callBackFunction) { } }; - xhttp.open("GET", pPath, true); - xhttp.send(); + if (pContentToSend === undefined) { + + xhttp.open("GET", pPath, true); + xhttp.send(); + + } else { + + let blob = new Blob([pContentToSend], { type: 'text/plain' }); + + xhttp.open("POST", pPath, true); + xhttp.send(blob); + + } } diff --git a/CloudVM/CloudVM.js b/CloudVM/CloudVM.js new file mode 100644 index 000000000..6b7957952 --- /dev/null +++ b/CloudVM/CloudVM.js @@ -0,0 +1,79 @@ + +function newCloudVM() { + + const MODULE_NAME = "CloudVM"; + const INFO_LOG = false; + const ERROR_LOG = true; + const logger = newWebDebugLog(); + logger.fileName = MODULE_NAME; + + var thisObject = { + onBotPlayPressed: onBotPlayPressed, + onBotStopPressed: onBotStopPressed + }; + + let root = newRoot(); + let intervalHandler; + let previousBotCode = ""; + + return thisObject; + + function onBotPlayPressed(pUI_COMMANDS) { + + window.SHALL_BOT_STOP = false; + + window.CURRENT_ENVIRONMENT = "Develop"; + window.STORAGE_PERMISSIONS = ecosystem.getStoragePermissions(); + window.EXCHANGE_KEYS = ecosystem.getExchangeKeys(); + window.USER_LOGGED_IN = window.localStorage.getItem("userName"); + window.USER_DEV_TEAM = window.localStorage.getItem("devTeam"); + + root.initialize(pUI_COMMANDS, onInitialized); + + function onInitialized() { + + root.start(); + + intervalHandler = setInterval(checkForChangesInBotCode, 10000); + + } + + } + + function onBotStopPressed() { + + window.SHALL_BOT_STOP = true; + + } + + function checkForChangesInBotCode() { + + let botFunction = newUserBot; + + if (botFunction !== undefined) { + + let currentBotCode = botFunction.toString(); + + if (previousBotCode !== "") { + + if (currentBotCode !== previousBotCode) { + + console.log("Bot code changes detected."); + + let path = "AABrowserAPI" + "/" + + "saveBotCode" + ; + + callServer(currentBotCode, path, onServerResponse); + + function onServerResponse(err) { + + console.log("Server responded: " + err); + } + } + } + + previousBotCode = currentBotCode; + } + } +} \ No newline at end of file diff --git a/CloudVM/PoloniexAPIClient.js b/CloudVM/PoloniexAPIClient.js index 7fab924f5..c144e4384 100644 --- a/CloudVM/PoloniexAPIClient.js +++ b/CloudVM/PoloniexAPIClient.js @@ -87,7 +87,7 @@ + pMarketAssetB ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { @@ -106,7 +106,7 @@ + pPositionId ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { @@ -127,7 +127,7 @@ + pAmountB ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { @@ -148,7 +148,7 @@ + pAmountB ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { @@ -169,7 +169,7 @@ + pPositionAmountB ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { @@ -187,7 +187,7 @@ + secret ; - callServer(path + "/NO-LOG", onServerResponse); + callServer(undefined, path + "/NO-LOG", onServerResponse); function onServerResponse(pServerResponse) { diff --git a/Dashboard.js b/Dashboard.js index c56b6d7ce..e9a1b2f68 100644 --- a/Dashboard.js +++ b/Dashboard.js @@ -89,7 +89,7 @@ function convertTimePeriodToName(pTimePeriod) { } } -let cloudVM = newRoot(); +let cloudVM = newCloudVM(); const DEBUG_START_UP_DELAY = 0 //3000; // This is a waiting time in case there is a need to debug the very first steps of initialization, to be able to hit F12 on time. const INITIAL_DEFAULT_MARKET = 2; // This is the market that will be shown when loading the site for the first time. diff --git a/Panels/TimeControlPanel.js b/Panels/TimeControlPanel.js index ce66a8d7d..ed780ab2b 100644 --- a/Panels/TimeControlPanel.js +++ b/Panels/TimeControlPanel.js @@ -199,13 +199,13 @@ function newTimeControlPanel() { case "Step Backwards": - pressStepBackwards(); + //pressStepBackwards(); break; case "Pause": //pressPause(); - onBotStopPressed(); + cloudVM.onBotStopPressed(); break; case "Step Forward": @@ -222,7 +222,7 @@ function newTimeControlPanel() { eventHandler: thisObject.container.eventHandler }; - onBotPlayPressed(UI_COMMANDS); + cloudVM.onBotPlayPressed(UI_COMMANDS); //pressPlayForward(); break; diff --git a/Project.njsproj b/Project.njsproj index d64639f83..c06abbfb7 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -29,12 +29,18 @@ true + + Code + Code + + Code + @@ -164,6 +170,7 @@ + diff --git a/index.html b/index.html index c9e85b804..b2179ef31 100644 --- a/index.html +++ b/index.html @@ -14,6 +14,7 @@ + diff --git a/server.js b/server.js index 3553404dd..09c0ab10d 100644 --- a/server.js +++ b/server.js @@ -7,6 +7,31 @@ if (CONSOLE_LOG === true) { console.log("[INFO] server -> Node Server Starting." let serverConfig; +global.DEFAULT_OK_RESPONSE = { + result: "Ok", + message: "Operation Succeeded" +}; + +global.DEFAULT_FAIL_RESPONSE = { + result: "Fail", + message: "Operation Failed" +}; + +global.DEFAULT_RETRY_RESPONSE = { + result: "Retry", + message: "Retry Later" +}; + +global.CUSTOM_OK_RESPONSE = { + result: "Ok, but check Message", + message: "Custom Message" +}; + +global.CUSTOM_FAIL_RESPONSE = { + result: "Fail Because", + message: "Custom Message" +}; + let githubData = new Map; let storageData = new Map; let fileSystemData = new Map; @@ -366,6 +391,34 @@ function onBrowserRequest(request, response) { } break; + case "AABrowserAPI": // This means the Scripts folder. + { + const AABROSER_API_MODULE = require('./AABrowserAPI/' + 'API'); + let api = AABROSER_API_MODULE.newAPI(); + + api.initialize(serverConfig); + + processPost(request, response, onPostReceived) + + function onPostReceived(pData) { + + switch (requestParameters[2]) { + + case "saveBotCode": { + api.saveBotCode(pData, onResponse); + break; + } + + } + + function onResponse(err, pResponse) { + + respondWithContent(JSON.stringify(pResponse), response); + } + } + } + break; + case "Scripts": // This means the Scripts folder. { @@ -967,3 +1020,26 @@ function returnEmptyArray() { } } +function processPost(request, response, callback) { + let data = ""; + if (typeof callback !== 'function') return null; + + if (request.method == 'POST') { + request.on('data', function (pData) { + data += pData; + if (data.length > 1e6) { + data = ""; + response.writeHead(413, { 'Content-Type': 'text/plain' }).end(); + request.connection.destroy(); + } + }); + + request.on('end', function () { + callback(data); + }); + + } else { + response.writeHead(405, { 'Content-Type': 'text/plain' }); + response.end(); + } +} \ No newline at end of file