diff --git a/Client/MultiProject.js b/Client/MultiProject.js new file mode 100644 index 000000000..21e8b08ef --- /dev/null +++ b/Client/MultiProject.js @@ -0,0 +1,73 @@ +exports.newMultiProject = function () { + + let thisObject = { + initialize: initialize + } + + return thisObject; + + function initialize() { + /* + First thing is to load the project schema file. + */ + let PROJECTS_SCHEMA = require(global.env.PATH_TO_PROJECTS_REQUIRED + '/' + 'ProjectsSchema.json') + + /* + Here we will setup the CL object, with all the + projects and modules that will have inside. + */ + global.CL = { + projects: {} + } + for (let i = 0; i < PROJECTS_SCHEMA.length; i++) { + let projectDefinition = PROJECTS_SCHEMA[i] + global.CL.projects[projectDefinition.propertyName] = {} + let projectInstance = global.CL.projects[projectDefinition.propertyName] + + projectInstance.utilities = {} + projectInstance.globals = {} + projectInstance.functionLibraries = {} + projectInstance.taskModules = {} + projectInstance.processModules = {} + projectInstance.botModules = {} + + if (projectDefinition.CL === undefined) { continue } + + /* Set up Utilities of this Project */ + if (projectDefinition.CL.utilities !== undefined) { + for (let j = 0; j < projectDefinition.CL.utilities.length; j++) { + let utilityDefinition = projectDefinition.CL.utilities[j] + let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Utilities' + '/' + utilityDefinition.fileName + + let requiredObject = require(path) + let requiredFunction = requiredObject[utilityDefinition.functionName] + projectInstance.utilities[utilityDefinition.propertyName] = requiredFunction.call() + } + } + + /* Set up Globals of this Project */ + if (projectDefinition.CL.globals !== undefined) { + for (let j = 0; j < projectDefinition.CL.globals.length; j++) { + let globalDefinition = projectDefinition.CL.globals[j] + let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Globals' + '/' + globalDefinition.fileName + + let requiredObject = require(path) + let requiredFunction = requiredObject[globalDefinition.functionName] + projectInstance.globals[globalDefinition.propertyName] = requiredFunction.call() + } + } + + /* Set up Function Libraries of this Project */ + if (projectDefinition.CL.functionLibraries !== undefined) { + for (let j = 0; j < projectDefinition.CL.functionLibraries.length; j++) { + let functionLibraryDefinition = projectDefinition.CL.functionLibraries[j] + let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Function-Libraries' + '/' + functionLibraryDefinition.fileName + + let requiredObject = require(path) + let requiredFunction = requiredObject[functionLibraryDefinition.functionName] + projectInstance.functionLibraries[functionLibraryDefinition.propertyName] = requiredFunction.call() + } + } + } + } +} \ No newline at end of file diff --git a/Client/client.js b/Client/client.js index 3c4d2d247..efd575240 100644 --- a/Client/client.js +++ b/Client/client.js @@ -64,12 +64,18 @@ let EVENT_SERVER = require('./eventServer.js') let TASK_MANAGER_SERVER = require('./taskManagerServer.js') let CCXT_SERVER = require('./ccxtServer.js') let WEB3_SERVER = require('./web3Server.js') +let GITHUB_SERVER = require('./githubServer.js') /* Network Interfaces */ let WEB_SOCKETS_INTERFACE = require('./webSocketsServer.js') let HTTP_INTERFACE = require('./httpInterface.js') try { + /* Setting up the modules that will be available for the Servers Running inside this Client */ + let MULTI_PROJECT = require('./MultiProject.js'); + let MULTI_PROJECT_MODULE = MULTI_PROJECT.newMultiProject() + MULTI_PROJECT_MODULE.initialize() + console.log('CLIENT SERVERS:') console.log('') @@ -87,7 +93,7 @@ try { PROJECT_FILE_SERVER.initialize() PROJECT_FILE_SERVER.run() console.log('Project File Server ......................................... Started') - + PLUGIN_SERVER = PLUGIN_SERVER.newPluginServer() PLUGIN_SERVER.initialize() PLUGIN_SERVER.run() @@ -112,12 +118,17 @@ try { CCXT_SERVER.initialize() CCXT_SERVER.run() console.log('CCXT Server ................................................. Started') - + WEB3_SERVER = WEB3_SERVER.newWeb3Server() WEB3_SERVER.initialize() WEB3_SERVER.run() console.log('WEB3 Server ................................................. Started') + GITHUB_SERVER = GITHUB_SERVER.newGithubServer() + GITHUB_SERVER.initialize() + GITHUB_SERVER.run() + console.log('Github Server ............................................... Started') + console.log('') console.log('CLIENT INTERFACES:') console.log('') @@ -127,7 +138,16 @@ try { WEB_SOCKETS_INTERFACE.run() console.log('Web Sockets Interface ....................................... Listening at port ' + global.env.WEB_SOCKETS_INTERFACE_PORT) - HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) + HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface( + WEB_SERVER, + DATA_FILE_SERVER, + PROJECT_FILE_SERVER, + UI_FILE_SERVER, + PLUGIN_SERVER, + CCXT_SERVER, + WEB3_SERVER, + GITHUB_SERVER + ) HTTP_INTERFACE.initialize() HTTP_INTERFACE.run() console.log('Http Interface .............................................. Listening at port ' + global.env.HTTP_INTERFACE_PORT) diff --git a/Client/githubServer.js b/Client/githubServer.js new file mode 100644 index 000000000..ea1f2f991 --- /dev/null +++ b/Client/githubServer.js @@ -0,0 +1,484 @@ +exports.newGithubServer = function newGithubServer() { + + const MODULE = "Github Server" + + let thisObject = { + getGithubStars: getGithubStars, + getGithubWatchers: getGithubWatchers, + getGithubForks: getGithubForks, + mergePullRequests: mergePullRequests, + initialize: initialize, + finalize: finalize, + run: run + } + + const GITHUB_API_WAITING_TIME = 250 + return thisObject + + function finalize() { + + } + + function initialize() { + + } + + function run() { + + } + + async function getGithubStars(repository, username, token) { + return await getGithubUsernames('activity', 'listStargazersForRepo', repository, username, token) + } + + async function getGithubWatchers(repository, username, token) { + return await getGithubUsernames('activity', 'listWatchersForRepo', repository, username, token) + } + + async function getGithubForks(repository, username, token) { + return await getGithubUsernames('repos', 'listForks', repository, username, token) + } + + async function mergePullRequests(commitMessage, username, token) { + return await mergeGithubPullRequests(commitMessage, username, token) + } + + async function getGithubUsernames(endpoint, method, repository, username, token) { + try { + + repository = unescape(repository) + username = unescape(username) + token = unescape(token) + let error + let githubListArray = [] + + return await getRepoInfo() + + async function getRepoInfo() { + await doGithub() + if (error !== undefined) { + + let docs = { + project: 'Governance', + category: 'Topic', + type: 'Gov Error - Get Repository Information', + anchor: undefined, + placeholder: {} + } + + return respondWithDocsObject(docs, error) + } + + return { + result: global.DEFAULT_OK_RESPONSE.result, + githubListArray: githubListArray + } + } + + async function doGithub() { + + const { Octokit } = require("@octokit/rest") + + const octokit = new Octokit({ + auth: token, + userAgent: 'Superalgos Beta 11' + }) + await getList() + + async function getList() { + const repo = repository + const owner = 'Superalgos' + const per_page = 100 // Max + let page = 0 + let lastPage = false + + while (lastPage === false) { + try { + page++ + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + let listResponse = await octokit[endpoint][method]({ + owner, + repo, + per_page, + page + }); + + if (listResponse.data.length < 100) { + lastPage = true + } + + for (let i = 0; i < listResponse.data.length; i++) { + let listItem = listResponse.data[i] + let githubUsername + switch (endpoint) { + case 'activity': { + githubUsername = listItem.login + break + } + case 'repos': { + githubUsername = listItem.owner.login + break + } + } + //console.log(listItem) + + githubListArray.push(githubUsername) + } + console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page) + console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length) + + } catch (err) { + console.log(err) + + if (err.stack.indexOf('last page') >= 0) { + return + } else { + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->Method call produced an error.') + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack) + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->repository = ' + repository) + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->username = ' + username) + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10)) + error = err + } + } + } + } + } + + } catch (err) { + console.log('[ERROR] Github Server -> getRepoInfo -> Method call produced an error.') + console.log('[ERROR] Github Server -> getRepoInfo -> err.stack = ' + err.stack) + console.log('[ERROR] Github Server -> getRepoInfo -> repository = ' + repository) + console.log('[ERROR] Github Server -> getRepoInfo -> username = ' + username) + console.log('[ERROR] Github Server -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] Github Server -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10)) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + return error + } + } + + async function mergeGithubPullRequests(commitMessage, username, token) { + try { + commitMessage = unescape(commitMessage) + username = unescape(username) + token = unescape(token) + const repository = 'Superalgos' + + /* Unsavping # */ + for (let i = 0; i < 10; i++) { + commitMessage = commitMessage.replace('_SLASH_', '/') + commitMessage = commitMessage.replace('_HASHTAG_', '#') + } + + let error + let githubPrListArray = [] + + return await processOpenPullRequests() + + async function processOpenPullRequests() { + await doGithub() + if (error !== undefined) { + + let docs = { + project: 'Governance', + category: 'Topic', + type: 'Gov Error - Merge Pull Requests', + anchor: undefined, + placeholder: {} + } + + return respondWithDocsObject(docs, error) + } + + return { + result: global.DEFAULT_OK_RESPONSE.result + } + } + + async function doGithub() { + try { + const repo = repository + const owner = 'Superalgos' + const { Octokit } = require("@octokit/rest") + const octokit = new Octokit({ + auth: token, + userAgent: 'Superalgos Beta 11' + }) + await getPrList() + await mergePrs() + + async function getPrList() { + + const per_page = 100 // Max + let page = 0 + let lastPage = false + + while (lastPage === false) { + try { + page++ + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + + let listResponse = await octokit.rest.pulls.list({ + owner: owner, + repo: repo, + state: 'open', + head: 'develop', + base: 'develop', + sort: undefined, + direction: undefined, + per_page: per_page, + page: page + }); + + if (listResponse.data.length < 100) { + lastPage = true + } + console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Receiving Page = ' + page) + for (let i = 0; i < listResponse.data.length; i++) { + let pullRequest = listResponse.data[i] + console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Pull Request "' + pullRequest.title + '" found and added to the list to validate. ') + githubPrListArray.push(pullRequest) + } + console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Received = ' + listResponse.data.length) + + } catch (err) { + console.log(err) + + if (err.stack.indexOf('last page') >= 0) { + return + } else { + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->Method call produced an error.') + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->err.stack = ' + err.stack) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->repository = ' + repository) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->username = ' + username) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token ends with = ' + '...' + token.substring(token.length - 10)) + error = err + } + } + } + } + + async function mergePrs() { + /* + In order to automatically merge a PRs we will run several validations first. + We want to automate specifically the merging of Profile File changes at the + Governance System done by the same Github user name that matches the profile + changed. We will also not do the merge if there are more than one file at the + PR. + + We will go through the list of open PRs and run the validations at each one of them. + */ + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Ready to Validate ' + githubPrListArray.length + ' pull requests. ') + + for (let i = 0; i < githubPrListArray.length; i++) { + let pullRequest = githubPrListArray[i] + /* + Lets get the files changed at this Pull Request. + */ + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + let listResponse = await octokit.rest.pulls.listFiles({ + owner: owner, + repo: repo, + pull_number: pullRequest.number + }); + /* + Validation #1: If the PR has more than one file, then we will not automatically + merge it. + */ + if (listResponse.data.length !== 1) { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #1 Failed -> Pull Request "' + pullRequest.title + '" not merged because it contains more than 1 file. -> fileCount = ' + listResponse.data.length) + /* + We will close PRs that contains any User Profile file together with other files in the same Pull Request. + This will avoid manual merges to include User Profile files. + */ + for (j = 0; j < listResponse.data.length; j++) { + let pullRequestFile = listResponse.data[j] + let fileContentUrl = pullRequestFile.raw_url + if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') >= 0) { + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: pullRequest.number, + body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (listResponse.data.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.' + }); + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.pulls.update({ + owner: owner, + repo: repo, + pull_number: pullRequest.number, + state: 'closed' + }); + break + } + } + continue + } + let pullRequestFile = listResponse.data[0] + /* + Validation #2: File Name must be the same to the Github Username of the PR owner. + */ + let fileContentUrl = pullRequestFile.raw_url + + if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') < 0) { + /* + If it is not a user profile then there is no need to auto merge. + */ + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified at the Pull Request is not a User Profile file. -> fileContentUrl = ' + fileContentUrl) + continue + } + + let splittedURL = fileContentUrl.split('/') + let fileName = splittedURL[splittedURL.length - 1] + let splittedFileName = fileName.split('.') + fileName = splittedFileName[0] + let githubUsername = pullRequest.user.login + + if (githubUsername !== fileName) { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the File Name. -> Github Username = ' + githubUsername + '-> fileName = ' + fileName) + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: pullRequest.number, + body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the name of the User Profile Plugin File.\n\n File Name = "' + fileName + '"' + }); + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.pulls.update({ + owner: owner, + repo: repo, + pull_number: pullRequest.number, + state: 'closed' + }); + continue + } + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + let fileContent = await fetchAPIDataFile(fileContentUrl) + + let userProfile = JSON.parse(fileContent) + /* + Validation #3: The file changed at the PR is a User Profile. + */ + if (userProfile.type !== 'User Profile') { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #3 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified is not a User Profile. -> Type = ' + userProfile.type) + continue + } + /* + Validation #4: The message signed at the config is not the Github Username. + */ + let config = JSON.parse(userProfile.config) + let messageSigned = config.signature.message + if (messageSigned !== githubUsername) { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #4 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the Message Signed at the User Profile. -> Github Username = ' + githubUsername + '-> messageSigned = ' + messageSigned) + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: pullRequest.number, + body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the Message Signed at the User Profile.\n\n Message Signed = "' + messageSigned + '"' + }); + + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.pulls.update({ + owner: owner, + repo: repo, + pull_number: pullRequest.number, + state: 'closed' + }); + continue + } + /* + All validations passed, we will proceed an merge this Pull Request. + */ + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + let mergeResponse = await octokit.rest.pulls.merge({ + owner: owner, + repo: repo, + pull_number: pullRequest.number, + commit_title: 'Changes in User Profile done by Profile Owner ' + githubUsername + ' automatically merged by Superalgos.' + }); + + if (mergeResponse.data.merged !== true) { + console.log('[WARN] Github Server -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message) + continue + } else { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Merge Succed -> Pull Request "' + pullRequest.title + '" successfully merged. -> mergeResponse.message = ' + mergeResponse.data.message) + await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: pullRequest.number, + body: 'This Pull Request was automatically merged by the Superalgos Governance System because it was detected that the Github User " ' + githubUsername + '" who submitted it, modified its own User Profile Plugin File and nothning else but that file. All validations were successfull.' + }); + continue + } + } + } + } catch (err) { + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> err.stack = ' + err.stack) + } + } + + } catch (err) { + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> Method call produced an error.') + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> err.stack = ' + err.stack) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> repository = ' + repository) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> username = ' + username) + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token starts with = ' + token.substring(0, 10) + '...') + console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token ends with = ' + '...' + token.substring(token.length - 10)) + + let error = { + result: 'Fail Because', + message: err.message, + stack: err.stack + } + return error + } + } + + function respondWithDocsObject(docs, error) { + + if (error.message !== undefined) { + docs.placeholder.errorMessage = { + style: 'Error', + text: error.message + } + } + if (error.stack !== undefined) { + docs.placeholder.errorStack = { + style: 'Javascript', + text: error.stack + } + } + if (error.code !== undefined) { + docs.placeholder.errorCode = { + style: 'Json', + text: error.code + } + } + + docs.placeholder.errorDetails = { + style: 'Json', + text: JSON.stringify(error, undefined, 4) + } + + let customResponse = { + result: global.CUSTOM_FAIL_RESPONSE.result, + docs: docs + } + + return customResponse + } +} \ No newline at end of file diff --git a/Client/httpInterface.js b/Client/httpInterface.js index 2389e5f7e..cabb56dae 100644 --- a/Client/httpInterface.js +++ b/Client/httpInterface.js @@ -1,4 +1,13 @@ -exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) { +exports.newHttpInterface = function newHttpInterface( + WEB_SERVER, + DATA_FILE_SERVER, + PROJECT_FILE_SERVER, + UI_FILE_SERVER, + PLUGIN_SERVER, + CCXT_SERVER, + WEB3_SERVER, + GITHUB_SERVER + ) { /* IMPORTANT: If you are reviewing the code of the project please note @@ -366,6 +375,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break } + case 'Save-Concept-Schema': { getBody(processRequest) @@ -396,6 +406,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break } + case 'Save-Topic-Schema': { getBody(processRequest) @@ -426,6 +437,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break } + case 'Save-Tutorial-Schema': { getBody(processRequest) @@ -456,6 +468,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break } + case 'Save-Review-Schema': { getBody(processRequest) @@ -486,6 +499,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break } + case 'Save-Book-Schema': { getBody(processRequest) @@ -1019,138 +1033,80 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } break - case 'Gov': { - switch (requestParameters[2]) { // switch by command - case 'getGithubStars': { - getGithubUsernames('activity', 'listStargazersForRepo') - break - } - case 'getGithubWatchers': { - getGithubUsernames('activity', 'listWatchersForRepo') - break - } - case 'getGithubForks': { - getGithubUsernames('repos', 'listForks') - break - } - case 'PRs': { - mergeGithubPullRequests() - break - } - case 'Pay': { - payToContributors() - break - } - } + case 'GOV': { + /* + This is the Governance endpoint at the Http Interface. All methods + related to the Governance System are implemented here and routed + to the backend Servers that can process them. + */ + getBody(processRequest) - function getGithubUsernames(endpoint, method) { + async function processRequest(body) { try { - const GITHUB_API_WAITING_TIME = 250 - const repository = unescape(requestParameters[3]) - const username = unescape(requestParameters[4]) - const token = unescape(requestParameters[5]) - let error - let githubListArray = [] + let params = JSON.parse(body) - getRepoInfo() + switch (params.method) { + case 'getGithubStars': { - async function getRepoInfo() { - await doGithub() - if (error !== undefined) { + let serverResponse = await GITHUB_SERVER.getGithubStars( + params.repository, + params.username, + params.token + ) - let docs = { - project: 'Governance', - category: 'Topic', - type: 'Gov Error - Get Repository Information', - anchor: undefined, - placeholder: {} - } - - respondWithDocsObject(docs, error) + respondWithContent(JSON.stringify(serverResponse), httpResponse) return } + case 'getGithubWatchers': { - respondWithContent(JSON.stringify(githubListArray), httpResponse) - } + let serverResponse = await GITHUB_SERVER.getGithubWatchers( + params.repository, + params.username, + params.token + ) - async function doGithub() { + respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'getGithubForks': { - const { Octokit } = require("@octokit/rest") + let serverResponse = await GITHUB_SERVER.getGithubForks( + params.repository, + params.username, + params.token + ) - const octokit = new Octokit({ - auth: token, - userAgent: 'Superalgos Beta 11' - }) - await getList() + respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'mergePullRequests': { - async function getList() { - const repo = repository - const owner = 'Superalgos' - const per_page = 100 // Max - let page = 0 - let lastPage = false + let serverResponse = await GITHUB_SERVER.mergePullRequests( + params.commitMessage, + params.username, + params.token + ) - while (lastPage === false) { - try { - page++ - await sleep(GITHUB_API_WAITING_TIME) - let listResponse = await octokit[endpoint][method]({ - owner, - repo, - per_page, - page - }); + respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + case 'payContributors': { - if (listResponse.data.length < 100) { - lastPage = true - } + let serverResponse = await WEB3_SERVER.payContributors( + params.signature + ) - for (let i = 0; i < listResponse.data.length; i++) { - let listItem = listResponse.data[i] - let githubUsername - switch (endpoint) { - case 'activity': { - githubUsername = listItem.login - break - } - case 'repos': { - githubUsername = listItem.owner.login - break - } - } - //console.log(listItem) - - githubListArray.push(githubUsername) - } - console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page) - console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length) - - } catch (err) { - console.log(err) - - if (err.stack.indexOf('last page') >= 0) { - return - } else { - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->repository = ' + repository) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10)) - error = err - } - } - } + respondWithContent(JSON.stringify(serverResponse), httpResponse) + return + } + default: { + respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse) } } - } catch (err) { - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> repository = ' + repository) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10)) + console.log('[ERROR] httpInterface -> GOV -> Method call produced an error.') + console.log('[ERROR] httpInterface -> GOV -> err.stack = ' + err.stack) + console.log('[ERROR] httpInterface -> GOV -> Params Received = ' + body) let error = { result: 'Fail Because', @@ -1160,333 +1116,8 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE respondWithContent(JSON.stringify(error), httpResponse) } } - - function respondWithDocsObject(docs, error) { - - if (error.message !== undefined) { - docs.placeholder.errorMessage = { - style: 'Error', - text: error.message - } - } - if (error.stack !== undefined) { - docs.placeholder.errorStack = { - style: 'Javascript', - text: error.stack - } - } - if (error.code !== undefined) { - docs.placeholder.errorCode = { - style: 'Json', - text: error.code - } - } - - docs.placeholder.errorDetails = { - style: 'Json', - text: JSON.stringify(error, undefined, 4) - } - - let customResponse = { - result: global.CUSTOM_FAIL_RESPONSE.result, - docs: docs - } - - respondWithContent(JSON.stringify(customResponse), httpResponse) - - } - - function mergeGithubPullRequests() { - try { - let commitMessage = unescape(requestParameters[3]) - - /* Unsavping # */ - for (let i = 0; i < 10; i++) { - commitMessage = commitMessage.replace('_SLASH_', '/') - commitMessage = commitMessage.replace('_HASHTAG_', '#') - } - - const GITHUB_API_WAITING_TIME = 250 - const repository = 'Superalgos' - const username = unescape(requestParameters[4]) - const token = unescape(requestParameters[5]) - - let error - let githubPrListArray = [] - - processOpenPullRequests() - - async function processOpenPullRequests() { - await doGithub() - if (error !== undefined) { - - let docs = { - project: 'Governance', - category: 'Topic', - type: 'Gov Error - Merge Pull Requests', - anchor: undefined, - placeholder: {} - } - - respondWithDocsObject(docs, error) - return - } - - respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), httpResponse) - } - - async function doGithub() { - try { - const repo = repository - const owner = 'Superalgos' - const { Octokit } = require("@octokit/rest") - const octokit = new Octokit({ - auth: token, - userAgent: 'Superalgos Beta 11' - }) - await getPrList() - await mergePrs() - - async function getPrList() { - - const per_page = 100 // Max - let page = 0 - let lastPage = false - - while (lastPage === false) { - try { - page++ - - await sleep(GITHUB_API_WAITING_TIME) - let listResponse = await octokit.rest.pulls.list({ - owner: owner, - repo: repo, - state: 'open', - head: 'develop', - base: 'develop', - sort: undefined, - direction: undefined, - per_page: per_page, - page: page - }); - - if (listResponse.data.length < 100) { - lastPage = true - } - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Receiving Page = ' + page) - for (let i = 0; i < listResponse.data.length; i++) { - let pullRequest = listResponse.data[i] - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Pull Request "' + pullRequest.title + '" found and added to the list to validate. ') - githubPrListArray.push(pullRequest) - } - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList -> Received = ' + listResponse.data.length) - - } catch (err) { - console.log(err) - - if (err.stack.indexOf('last page') >= 0) { - return - } else { - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->repository = ' + repository) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> getPrList ->token ends with = ' + '...' + token.substring(token.length - 10)) - error = err - } - } - } - } - - async function mergePrs() { - /* - In order to automatically merge a PRs we will run several validations first. - We want to automate specifically the merging of Profile File changes at the - Governance System done by the same Github user name that matches the profile - changed. We will also not do the merge if there are more than one file at the - PR. - - We will go through the list of open PRs and run the validations at each one of them. - */ - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Ready to Validate ' + githubPrListArray.length + ' pull requests. ') - - for (let i = 0; i < githubPrListArray.length; i++) { - let pullRequest = githubPrListArray[i] - /* - Lets get the files changed at this Pull Request. - */ - await sleep(GITHUB_API_WAITING_TIME) - let listResponse = await octokit.rest.pulls.listFiles({ - owner: owner, - repo: repo, - pull_number: pullRequest.number - }); - /* - Validation #1: If the PR has more than one file, then we will not automatically - merge it. - */ - if (listResponse.data.length !== 1) { - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #1 Failed -> Pull Request "' + pullRequest.title + '" not merged because it contains more than 1 file. -> fileCount = ' + listResponse.data.length) - /* - We will close PRs that contains any User Profile file together with other files in the same Pull Request. - This will avoid manual merges to include User Profile files. - */ - for (j = 0; j < listResponse.data.length; j++) { - let pullRequestFile = listResponse.data[j] - let fileContentUrl = pullRequestFile.raw_url - if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') >= 0) { - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: pullRequest.number, - body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (listResponse.data.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.' - }); - - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.pulls.update({ - owner: owner, - repo: repo, - pull_number: pullRequest.number, - state: 'closed' - }); - break - } - } - continue - } - let pullRequestFile = listResponse.data[0] - /* - Validation #2: File Name must be the same to the Github Username of the PR owner. - */ - let fileContentUrl = pullRequestFile.raw_url - - if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') < 0) { - /* - If it is not a user profile then there is no need to auto merge. - */ - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified at the Pull Request is not a User Profile file. -> fileContentUrl = ' + fileContentUrl) - continue - } - - let splittedURL = fileContentUrl.split('/') - let fileName = splittedURL[splittedURL.length - 1] - let splittedFileName = fileName.split('.') - fileName = splittedFileName[0] - let githubUsername = pullRequest.user.login - - if (githubUsername !== fileName) { - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the File Name. -> Github Username = ' + githubUsername + '-> fileName = ' + fileName) - - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: pullRequest.number, - body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the name of the User Profile Plugin File.\n\n File Name = "' + fileName + '"' - }); - - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.pulls.update({ - owner: owner, - repo: repo, - pull_number: pullRequest.number, - state: 'closed' - }); - continue - } - await sleep(GITHUB_API_WAITING_TIME) - let fileContent = await fetchAPIDataFile(fileContentUrl) - - let userProfile = JSON.parse(fileContent) - /* - Validation #3: The file changed at the PR is a User Profile. - */ - if (userProfile.type !== 'User Profile') { - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #3 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified is not a User Profile. -> Type = ' + userProfile.type) - continue - } - /* - Validation #4: The message signed at the config is not the Github Username. - */ - let config = JSON.parse(userProfile.config) - let messageSigned = config.signature.message - if (messageSigned !== githubUsername) { - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Validation #4 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the Message Signed at the User Profile. -> Github Username = ' + githubUsername + '-> messageSigned = ' + messageSigned) - - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: pullRequest.number, - body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the Message Signed at the User Profile.\n\n Message Signed = "' + messageSigned + '"' - }); - - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.pulls.update({ - owner: owner, - repo: repo, - pull_number: pullRequest.number, - state: 'closed' - }); - continue - } - /* - All validations passed, we will proceed an merge this Pull Request. - */ - await sleep(GITHUB_API_WAITING_TIME) - let mergeResponse = await octokit.rest.pulls.merge({ - owner: owner, - repo: repo, - pull_number: pullRequest.number, - commit_title: 'Changes in User Profile done by Profile Owner ' + githubUsername + ' automatically merged by Superalgos.' - }); - - if (mergeResponse.data.merged !== true) { - console.log('[WARN] httpInterface -> Gov -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message) - continue - } else { - console.log('[INFO] httpInterface -> Gov -> mergeGithubPullRequests -> Merge Succed -> Pull Request "' + pullRequest.title + '" successfully merged. -> mergeResponse.message = ' + mergeResponse.data.message) - await sleep(GITHUB_API_WAITING_TIME) - await octokit.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: pullRequest.number, - body: 'This Pull Request was automatically merged by the Superalgos Governance System because it was detected that the Github User " ' + githubUsername + '" who submitted it, modified its own User Profile Plugin File and nothning else but that file. All validations were successfull.' - }); - continue - } - } - } - } catch (err) { - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> doGithub -> err.stack = ' + err.stack) - } - } - - } catch (err) { - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> Method call produced an error.') - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> err.stack = ' + err.stack) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> repository = ' + repository) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> username = ' + username) - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> token starts with = ' + token.substring(0, 10) + '...') - console.log('[ERROR] httpInterface -> Gov -> mergeGithubPullRequests -> token ends with = ' + '...' + token.substring(token.length - 10)) - - let error = { - result: 'Fail Because', - message: err.message, - stack: err.stack - } - respondWithContent(JSON.stringify(error), httpResponse) - } - } - - function payToContributors() { - - } - } break - + } case 'LegacyPlotter.js': { respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/LegacyPlotter.js', httpResponse) @@ -2432,12 +2063,6 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE } } - function sleep(ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms) - }) - } - async function fetchAPIDataFile(url) { let promise = new Promise((resolve, reject) => { diff --git a/Projects/Foundations/CL/Utilities/AsyncFunctions.js b/Projects/Foundations/CL/Utilities/AsyncFunctions.js new file mode 100644 index 000000000..d2cb60141 --- /dev/null +++ b/Projects/Foundations/CL/Utilities/AsyncFunctions.js @@ -0,0 +1,14 @@ +exports.newFoundationsUtilitiesAsyncFunctions = function () { + + let thisObject = { + sleep: sleep + } + + return thisObject + + function sleep(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms) + }) + } +} \ No newline at end of file diff --git a/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js b/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js index 907ab42cd..d3fda57e7 100644 --- a/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js +++ b/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js @@ -157,7 +157,10 @@ function newWorkspace() { let workspace = UI.projects.foundations.spaces.designSpace.workspace.workspaceNode /* Validation if it is too early to save. */ - if (thisObject.isInitialized === false) { return } + if (thisObject.isInitialized === false) { + console.log('Workspace not saved because it has not been initialized. =') + return + } /* Validation of 2 sessions opened at the same time. */ let savedSessionTimestamp = window.localStorage.getItem('Session Timestamp') diff --git a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json index 245c7569a..7173e6fbf 100644 --- a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json @@ -81,12 +81,12 @@ "id": "bda21833-11b8-49d3-8c79-ff8e1c667dcc", "savedPayload": { "position": { - "x": 31000.07168984726, - "y": 23974.264068711924 + "x": 30936.297332942388, + "y": 24042.62315256192 }, "targetPosition": { - "x": 30787.939655491296, - "y": 23762.13203435596 + "x": 30747.501215627435, + "y": 23809.47936412483 }, "floatingObject": { "isPinned": false, @@ -114,7 +114,7 @@ "floatingObject": { "isPinned": false, "isFrozen": false, - "isCollapsed": true, + "isCollapsed": false, "angleToParent": 3, "distanceToParent": 3, "arrangementStyle": 0 diff --git a/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js b/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js index 0cb3f4a2f..7f07298e3 100644 --- a/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js +++ b/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js @@ -31,7 +31,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { entropy: node.id + (new Date()).valueOf() } - let url = 'WEB3' // we don't need to ask this to any specific superalgos node. + let url = 'WEB3' // We will access the default Client WEB3 endpoint. httpRequest(JSON.stringify(params), url, onResponse) diff --git a/Projects/Governance/UI/Spaces/Reports-Space/CommandInterface.js b/Projects/Governance/UI/Spaces/Reports-Space/CommandInterface.js index fbde90f88..d9d5ad775 100644 --- a/Projects/Governance/UI/Spaces/Reports-Space/CommandInterface.js +++ b/Projects/Governance/UI/Spaces/Reports-Space/CommandInterface.js @@ -41,6 +41,10 @@ function newGovernanceReportsCommmandInterface() { message = 'Automated PR merging process.' } + /* Closing the Governance Tab */ + UI.projects.governance.spaces.reportsSpace.sidePanelTab.close() + UI.projects.education.spaces.docsSpace.sidePanelTab.open() + /* Find the Username and Password */ let apisNode = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadByNodeType('APIs') if (apisNode === undefined) { @@ -62,36 +66,53 @@ function newGovernanceReportsCommmandInterface() { return } + UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Processing Pull Requests') + message = message.replaceAll('#', '_HASHTAG_') message = message.replaceAll('/', '_SLASH_') - httpRequest( - undefined, - 'Gov/PRs/' + - message + '/' + - config.username + '/' + - config.token + '/' + - UI.projects.education.spaces.docsSpace.currentBranch + '/' + - UI.projects.education.spaces.docsSpace.contributionsBranch - , onResponse) + /* Lets execute this command against the Client */ - UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Processing Pull Requests') + let params = { + method: 'mergePullRequests', + commitMessage: message, + username: config.username, + token: config.token + } - return + let url = 'GOV' // We will access the default Client GOV endpoint. + + httpRequest(JSON.stringify(params), url, onResponse) function onResponse(err, data) { + /* Lets check the result of the call through the http interface */ - data = JSON.parse(data) - if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result && data.result === GLOBAL.DEFAULT_OK_RESPONSE.result) { + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call via HTTP Interface failed.' + err.stack) + console.log('[ERROR] Params = ' + JSON.stringify(params)) + return + } + + let response = JSON.parse(data) + + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call to Client Github Server failed.' + err.stack) + console.log('[ERROR] Params = ' + JSON.stringify(params)) + } + + /* Successful Call */ + + if (response.result === GLOBAL.DEFAULT_OK_RESPONSE.result) { UI.projects.education.spaces.docsSpace.navigateTo('Governance', 'Topic', 'Gov Message - Pull Requests Processed') } else { UI.projects.education.spaces.docsSpace.navigateTo( - data.docs.project, - data.docs.category, - data.docs.type, - data.docs.anchor, + response.docs.project, + response.docs.category, + response.docs.type, + response.docs.anchor, undefined, - data.docs.placeholder + response.docs.placeholder ) } } diff --git a/Projects/Governance/UI/Spaces/Reports-Space/ReportsSpace.js b/Projects/Governance/UI/Spaces/Reports-Space/ReportsSpace.js index 5790330d2..3487a3c57 100644 --- a/Projects/Governance/UI/Spaces/Reports-Space/ReportsSpace.js +++ b/Projects/Governance/UI/Spaces/Reports-Space/ReportsSpace.js @@ -231,15 +231,6 @@ function newGobernanceReportsSpace() { 'width: ' + thisObject.container.frame.width + 'px;' + 'height: ' + thisObject.container.frame.height + 'px' } - - /* - Monitor the Docs Space to see if its tab is opened, to close this space tab. - */ - if (UI.projects.education.spaces.docsSpace.sidePanelTab.isOpen === true && - thisObject.sidePanelTab.isOpen === true - ) { - thisObject.sidePanelTab.close() - } } function getContainer(point, purpose) { diff --git a/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js b/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js index 55723d405..0166c361a 100644 --- a/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js +++ b/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js @@ -37,7 +37,7 @@ function newGovernanceUserProfileSpace() { If the workspace is not related to governance, then we exit the Intialize Function */ let resultsArary = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadsByNodeType('User Profile') - if (resultsArary.length === 0 || resultsArary.length === 1) { return } + if (resultsArary.length === 0) { return } /* Find the Username and Password */ @@ -68,69 +68,135 @@ function newGovernanceUserProfileSpace() { requestStars() function requestStars() { - httpRequest( - undefined, - 'Gov/getGithubStars/' + - 'Superalgos' + '/' + - config.username + '/' + - config.token - , onGithubStarsResponse) + + let params = { + method: 'getGithubStars', + repository: 'Superalgos', + username: config.username, + token: config.token + } + + let url = 'GOV' // We will access the default Client GOV endpoint. + + httpRequest(JSON.stringify(params), url, onResponse) + + function onResponse(err, data) { + + /* Lets check the result of the call through the http interface */ + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + return + } + + let response = JSON.parse(data) + + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + console.log('[ERROR] response = ' + JSON.stringify(response)) + return + } + + /* Successful Call */ + + let githubStarsArray = response.githubListArray + + for (let i = 0; i < githubStarsArray.length; i++) { + let githubUsername = githubStarsArray[i] + thisObject.githubStars.set(githubUsername, 1) + } + + requestWatchers() + } } function requestWatchers() { - httpRequest( - undefined, - 'Gov/getGithubWatchers/' + - 'Superalgos' + '/' + - config.username + '/' + - config.token - , onGithubWatchersResponse) + + let params = { + method: 'getGithubWatchers', + repository: 'Superalgos', + username: config.username, + token: config.token + } + + let url = 'GOV' // We will access the default Client GOV endpoint. + + httpRequest(JSON.stringify(params), url, onResponse) + + function onResponse(err, data) { + + /* Lets check the result of the call through the http interface */ + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + return + } + + let response = JSON.parse(data) + + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + console.log('[ERROR] response = ' + JSON.stringify(response)) + return + } + + /* Successful Call */ + + let githubWatchersArray = response.githubListArray + + for (let i = 0; i < githubWatchersArray.length; i++) { + let githubUsername = githubWatchersArray[i] + thisObject.githubWatchers.set(githubUsername, 1) + } + + requestForks() + } } function requestForks() { - httpRequest( - undefined, - 'Gov/getGithubForks/' + - 'Superalgos' + '/' + - config.username + '/' + - config.token - , onGithubForksResponse) - } - function onGithubStarsResponse(err, githubData) { - //console.log(githubData) - /* Lets check the result of the call through the http interface */ - let githubStarsArray = JSON.parse(githubData) - - for (let i = 0; i < githubStarsArray.length; i++) { - let githubUsername = githubStarsArray[i] - thisObject.githubStars.set(githubUsername, 1) + let params = { + method: 'getGithubForks', + repository: 'Superalgos', + username: config.username, + token: config.token } - requestWatchers() - } + let url = 'GOV' // We will access the default Client GOV endpoint. - function onGithubWatchersResponse(err, githubData) { - //console.log(githubData) - /* Lets check the result of the call through the http interface */ - let githubWatchersArray = JSON.parse(githubData) + httpRequest(JSON.stringify(params), url, onResponse) - for (let i = 0; i < githubWatchersArray.length; i++) { - let githubUsername = githubWatchersArray[i] - thisObject.githubWatchers.set(githubUsername, 1) - } + function onResponse(err, data) { - requestForks() - } + /* Lets check the result of the call through the http interface */ + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call via HTTP Interface failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + return + } - function onGithubForksResponse(err, githubData) { - //console.log(githubData) - /* Lets check the result of the call through the http interface */ - let githubForksArray = JSON.parse(githubData) + let response = JSON.parse(data) - for (let i = 0; i < githubForksArray.length; i++) { - let githubUsername = githubForksArray[i] - thisObject.githubForks.set(githubUsername, 1) + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + console.log('[ERROR] Call to Client Github Server failed. err.stack = ' + err.stack) + console.log('[ERROR] params = ' + JSON.stringify(params)) + console.log('[ERROR] response = ' + JSON.stringify(response)) + return + } + + /* Successful Call */ + + let githubForksArray = response.githubListArray + + for (let i = 0; i < githubForksArray.length; i++) { + let githubUsername = githubForksArray[i] + thisObject.githubForks.set(githubUsername, 1) + } } } } diff --git a/Projects/ProjectsSchema.json b/Projects/ProjectsSchema.json index f5b0499ae..2b289b65d 100644 --- a/Projects/ProjectsSchema.json +++ b/Projects/ProjectsSchema.json @@ -871,7 +871,16 @@ } ] }, - "CL": {}, + "CL": { + "utilities": [ + { + "name": "Async Function", + "propertyName": "asyncFunctions", + "functionName": "newFoundationsUtilitiesAsyncFunctions", + "fileName": "AsyncFunctions.js" + } + ] + }, "plugins": [ "Data Mines", "Trading Mines", diff --git a/TaskServer/MultiProject.js b/TaskServer/MultiProject.js index 3ab9fd525..cb64d2d0b 100644 --- a/TaskServer/MultiProject.js +++ b/TaskServer/MultiProject.js @@ -31,6 +31,8 @@ exports.newMultiProject = function () { projectInstance.processModules = {} projectInstance.botModules = {} + if (projectDefinition.TS === undefined) { continue } + /* Set up Utilities of this Project */ if (projectDefinition.TS.utilities !== undefined) { for (let j = 0; j < projectDefinition.TS.utilities.length; j++) {