mirror of
https://github.com/Hopiu/webapi-eca.git
synced 2026-03-16 22:10:31 +00:00
Debugging tools and use case implementation
This commit is contained in:
parent
8346b8bd7d
commit
003fe4111d
20 changed files with 514 additions and 207 deletions
18
README.md
18
README.md
|
|
@ -43,7 +43,7 @@ Apply your settings, for example:
|
||||||
"io-level": "info", # the log-level for the std I/O stream
|
"io-level": "info", # the log-level for the std I/O stream
|
||||||
"file-level": "info", # the log-level for the log file
|
"file-level": "info", # the log-level for the log file
|
||||||
"file-path": "server.log" # log file path, relative to cwd
|
"file-path": "server.log" # log file path, relative to cwd
|
||||||
( add "nolog": "true" if no log shall be generated at all. Mainly used for unit tests )
|
"nolog": "false" # false if no log shall be generated at all. Mainly used for unit tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,9 +54,13 @@ Start the server:
|
||||||
*Congratulations, your own WebAPI based ECA engine server is now up and running!*
|
*Congratulations, your own WebAPI based ECA engine server is now up and running!*
|
||||||
|
|
||||||
|
|
||||||
Optional command line tools:
|
Optional command line scripts
|
||||||
----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
Run test suite:
|
||||||
|
|
||||||
|
run_tests.sh
|
||||||
|
|
||||||
Create the doc *(to be accessed via the webserver, e.g.: localhost:8125/doc/)*:
|
Create the doc *(to be accessed via the webserver, e.g.: localhost:8125/doc/)*:
|
||||||
|
|
||||||
> **WARNING:**
|
> **WARNING:**
|
||||||
|
|
@ -65,8 +69,4 @@ Create the doc *(to be accessed via the webserver, e.g.: localhost:8125/doc/)*:
|
||||||
|
|
||||||
> *`!!! 5` needs to be relaced with `doctype html`*
|
> *`!!! 5` needs to be relaced with `doctype html`*
|
||||||
|
|
||||||
run_doc.sh
|
run_doc.sh
|
||||||
|
|
||||||
Run test suite:
|
|
||||||
|
|
||||||
run_tests.sh
|
|
||||||
|
|
@ -177,7 +177,7 @@ forgeModule = ( user, oPayload, dbMod, callback ) =>
|
||||||
if answ.code is 200
|
if answ.code is 200
|
||||||
funcs = []
|
funcs = []
|
||||||
funcs.push name for name, id of cm.module
|
funcs.push name for name, id of cm.module
|
||||||
@log.info "CM | Storing new module with functions #{ funcs.join() }"
|
@log.info "CM | Storing new module with functions #{ funcs.join( ', ' ) }"
|
||||||
answ.message =
|
answ.message =
|
||||||
" Module #{ oPayload.id } successfully stored! Found following function(s): #{ funcs }"
|
" Module #{ oPayload.id } successfully stored! Found following function(s): #{ funcs }"
|
||||||
oPayload.functions = JSON.stringify funcs
|
oPayload.functions = JSON.stringify funcs
|
||||||
|
|
|
||||||
|
|
@ -49,20 +49,15 @@ exports.getPublicKey = () =>
|
||||||
|
|
||||||
|
|
||||||
issueApiCall = ( logger ) ->
|
issueApiCall = ( logger ) ->
|
||||||
( method, url, credentials, cb ) ->
|
( method, url, data, options, cb ) ->
|
||||||
try
|
try
|
||||||
if method is 'get'
|
needle.request method, url, data, options, ( err, resp, body ) =>
|
||||||
func = needle.get
|
|
||||||
else
|
|
||||||
func = needle.post
|
|
||||||
|
|
||||||
func url, credentials, ( err, resp, body ) =>
|
|
||||||
try
|
try
|
||||||
cb err, resp, body
|
cb err, resp, body
|
||||||
catch err
|
catch err
|
||||||
logger 'Error during apicall! ' + err.message
|
logger 'Error during needle request! ' + err.message
|
||||||
catch err
|
catch err
|
||||||
logger 'Error before apicall! ' + err.message
|
logger 'Error before needle request! ' + err.message
|
||||||
|
|
||||||
logFunction = ( uId, rId, mId ) ->
|
logFunction = ( uId, rId, mId ) ->
|
||||||
( msg ) ->
|
( msg ) ->
|
||||||
|
|
@ -108,10 +103,9 @@ exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) =>
|
||||||
sandbox =
|
sandbox =
|
||||||
id: userId + '.' + modId + '.vm'
|
id: userId + '.' + modId + '.vm'
|
||||||
params: params
|
params: params
|
||||||
apicall: issueApiCall logFunc
|
needlereq: issueApiCall logFunc
|
||||||
# needle: needle
|
|
||||||
log: logFunc
|
log: logFunc
|
||||||
# debug: console.log
|
debug: console.log
|
||||||
exports: {}
|
exports: {}
|
||||||
|
|
||||||
#TODO child_process to run module!
|
#TODO child_process to run module!
|
||||||
|
|
@ -124,7 +118,10 @@ exports.compileString = ( src, userId, ruleId, modId, lang, dbMod, cb ) =>
|
||||||
# Start Node with the flags —nouse_idle_notification and —expose_gc, and then when you want to run the GC, just call global.gc().
|
# Start Node with the flags —nouse_idle_notification and —expose_gc, and then when you want to run the GC, just call global.gc().
|
||||||
catch err
|
catch err
|
||||||
answ.code = 400
|
answ.code = 400
|
||||||
answ.message = 'Loading Module failed: ' + err.message
|
msg = err.message
|
||||||
|
if not msg
|
||||||
|
msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number'
|
||||||
|
answ.message = 'Loading Module failed: ' + msg
|
||||||
cb
|
cb
|
||||||
answ: answ
|
answ: answ
|
||||||
module: sandbox.exports
|
module: sandbox.exports
|
||||||
|
|
|
||||||
6
examples/action-invokers/continuously.coffee
Normal file
6
examples/action-invokers/continuously.coffee
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#
|
||||||
|
# Pushes an event into the system each time the function is polled
|
||||||
|
#
|
||||||
|
exports.push = ( pushEvent ) ->
|
||||||
|
pushEvent
|
||||||
|
content: "This is an event that will be sent again and again every ten seconds"
|
||||||
142
examples/action-invokers/probinder.coffee
Normal file
142
examples/action-invokers/probinder.coffee
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
|
||||||
|
###
|
||||||
|
ProBinder ACTION INVOKER
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Global variables
|
||||||
|
This module requires user-specific parameters:
|
||||||
|
- username
|
||||||
|
- password
|
||||||
|
- companyId: company where to post the binder entries
|
||||||
|
- contextId: context where to post the binder entries
|
||||||
|
###
|
||||||
|
urlService = 'https://probinder.com/service/'
|
||||||
|
credentials =
|
||||||
|
username: params.username
|
||||||
|
password: params.password
|
||||||
|
|
||||||
|
#
|
||||||
|
# The standard callback can be used if callback is not provided, e.g. if
|
||||||
|
# the function is called from outside
|
||||||
|
#
|
||||||
|
standardCallback = ( funcName ) ->
|
||||||
|
( err, resp, body ) ->
|
||||||
|
if err
|
||||||
|
log "ERROR: During function '#{ funcName }'"
|
||||||
|
else
|
||||||
|
if resp.statusCode is 200
|
||||||
|
log "Function '#{ funcName }' ran through without error"
|
||||||
|
else
|
||||||
|
log "ERROR: During function '#{ funcName }': #{ body.error.message }"
|
||||||
|
|
||||||
|
###
|
||||||
|
Call the ProBinder service with the given parameters.
|
||||||
|
|
||||||
|
@param {Object} args the required function arguments object
|
||||||
|
@param {Object} [args.data] the data to be posted
|
||||||
|
@param {String} args.service the required service identifier to be appended to the url
|
||||||
|
@param {String} args.method the required method identifier to be appended to the url
|
||||||
|
@param {function} [args.callback] the function to receive the request answer
|
||||||
|
###
|
||||||
|
exports.call = ( args ) ->
|
||||||
|
if not args.service or not args.method
|
||||||
|
log 'ERROR in call function: Missing arguments!'
|
||||||
|
else
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'call'
|
||||||
|
url = urlService + args.service + '/' + args.method
|
||||||
|
needlereq 'post', url, args.data, credentials, args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Calls the user's unread content service.
|
||||||
|
|
||||||
|
@param {Object} [args] the optional object containing the callback function
|
||||||
|
@param {function} [args.callback] refer to call function
|
||||||
|
###
|
||||||
|
exports.getUnreadContents = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'getUnreadContents'
|
||||||
|
exports.call
|
||||||
|
service: '36'
|
||||||
|
method: 'unreadcontent'
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Calls the content get service with the content id and the service id provided.
|
||||||
|
|
||||||
|
@param {Object} args the object containing the service id and the content id,
|
||||||
|
success and error callback methods
|
||||||
|
@param {String} args.serviceid the service id that is able to process this content
|
||||||
|
@param {String} args.contentid the content id
|
||||||
|
@param {function} [args.callback] receives the needle answer from the "call" function
|
||||||
|
###
|
||||||
|
exports.getContent = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'getContent'
|
||||||
|
exports.call
|
||||||
|
service: '2'
|
||||||
|
method: 'get'
|
||||||
|
data:
|
||||||
|
id: args.contentid
|
||||||
|
service: args.serviceid
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Does everything to post something in a binder
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.content the content to be posted
|
||||||
|
###
|
||||||
|
exports.newContent = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'newContent'
|
||||||
|
exports.call
|
||||||
|
service: '27'
|
||||||
|
method: 'save'
|
||||||
|
data:
|
||||||
|
companyId: params.companyId
|
||||||
|
context: params.contextId
|
||||||
|
text: args.content
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Does everything to post a file info in a binder tabe
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.service the content service
|
||||||
|
@param {String} args.id the content id
|
||||||
|
###
|
||||||
|
exports.makeFileEntry = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'makeFileEntry'
|
||||||
|
exports.getContent
|
||||||
|
serviceid: args.service
|
||||||
|
contentid: args.id
|
||||||
|
callback: ( err, resp, body ) ->
|
||||||
|
exports.call
|
||||||
|
service: '27'
|
||||||
|
method: 'save'
|
||||||
|
data:
|
||||||
|
companyId: params.companyId
|
||||||
|
context: params.contextId
|
||||||
|
text: "New file (#{ body.title }) in tab \"#{ body.context[0].name }\",
|
||||||
|
find it <a href=\"https://probinder.com/file/#{ body.fileIds[0] }\">here</a>!'"
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Sets the content as read.
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.content the content to be posted
|
||||||
|
###
|
||||||
|
exports.setRead = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'setRead'
|
||||||
|
exports.call
|
||||||
|
service: '2'
|
||||||
|
method: 'setread'
|
||||||
|
data:
|
||||||
|
id: args.id
|
||||||
|
callback: args.callback
|
||||||
26
examples/event-pollers/emailyak.coffee
Normal file
26
examples/event-pollers/emailyak.coffee
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#
|
||||||
|
# EmailYak EVENT POLLER
|
||||||
|
# ---------------------
|
||||||
|
#
|
||||||
|
# Requires user params:
|
||||||
|
# - apikey: The user's EmailYak API key
|
||||||
|
#
|
||||||
|
|
||||||
|
url = 'https://api.emailyak.com/v1/' + params.apikey + '/json/get/new/email/'
|
||||||
|
|
||||||
|
exports.newMail = ( pushEvent ) ->
|
||||||
|
|
||||||
|
# needlereq allows the user to make calls to API's
|
||||||
|
# Refer to https://github.com/tomas/needle for more information
|
||||||
|
#
|
||||||
|
# Syntax: needle.request method, url, data, [options], callback
|
||||||
|
#
|
||||||
|
needlereq 'get', url, null, null, ( err, resp, body ) ->
|
||||||
|
if err
|
||||||
|
log 'Error in EmailYak EM newMail: ' + err.message
|
||||||
|
else
|
||||||
|
if resp.statusCode is 200
|
||||||
|
mails = JSON.parse( body ).Emails
|
||||||
|
pushEvent mail for mail in mails
|
||||||
|
|
||||||
37
examples/runscript.coffee
Normal file
37
examples/runscript.coffee
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
###
|
||||||
|
runscript.js
|
||||||
|
------------
|
||||||
|
|
||||||
|
A script that helps to track errors happening durin coffee
|
||||||
|
compilation and running of module code
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
if not process.argv[ 2 ]
|
||||||
|
console.log 'Please provide a path to a coffee file'
|
||||||
|
process.exit()
|
||||||
|
|
||||||
|
fs = require 'fs'
|
||||||
|
vm = require 'vm'
|
||||||
|
cs = require 'coffee-script'
|
||||||
|
|
||||||
|
issueApiCall = ( method, url, data, options, cb ) ->
|
||||||
|
cb new Error 'not possible'
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
data = fs.readFileSync process.argv[ 2 ], 'utf8'
|
||||||
|
src = cs.compile data
|
||||||
|
|
||||||
|
sandbox =
|
||||||
|
id: 'test.vm'
|
||||||
|
params: params
|
||||||
|
needlereq: issueApiCall
|
||||||
|
log: console.log
|
||||||
|
debug: console.log
|
||||||
|
exports: {}
|
||||||
|
|
||||||
|
vm.runInNewContext src, sandbox, sandbox.id
|
||||||
|
|
||||||
|
console.log "If no error happened until here it seems the script
|
||||||
|
compiled and ran correctly! Congrats!"
|
||||||
39
examples/runscript.js
Normal file
39
examples/runscript.js
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Generated by CoffeeScript 1.7.1
|
||||||
|
(function() {
|
||||||
|
var cs, data, fs, issueApiCall, params, sandbox, src, vm;
|
||||||
|
|
||||||
|
if (!process.argv[2]) {
|
||||||
|
console.log('Please provide a path to a coffee file');
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fs = require('fs');
|
||||||
|
|
||||||
|
vm = require('vm');
|
||||||
|
|
||||||
|
cs = require('coffee-script');
|
||||||
|
|
||||||
|
issueApiCall = function(method, url, data, options, cb) {
|
||||||
|
return cb(new Error('not possible'));
|
||||||
|
};
|
||||||
|
|
||||||
|
params = {};
|
||||||
|
|
||||||
|
data = fs.readFileSync(process.argv[2], 'utf8');
|
||||||
|
|
||||||
|
src = cs.compile(data);
|
||||||
|
|
||||||
|
sandbox = {
|
||||||
|
id: 'test.vm',
|
||||||
|
params: params,
|
||||||
|
needlereq: issueApiCall,
|
||||||
|
log: console.log,
|
||||||
|
debug: console.log,
|
||||||
|
exports: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.runInNewContext(src, sandbox, sandbox.id);
|
||||||
|
|
||||||
|
console.log('If no error happened until here it seems the script compiled and ran correctly! Congrats!');
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|
@ -246,7 +246,7 @@ Components Manager
|
||||||
id = _ref[name];
|
id = _ref[name];
|
||||||
funcs.push(name);
|
funcs.push(name);
|
||||||
}
|
}
|
||||||
_this.log.info("CM | Storing new module with functions " + (funcs.join()));
|
_this.log.info("CM | Storing new module with functions " + (funcs.join(', ')));
|
||||||
answ.message = " Module " + oPayload.id + " successfully stored! Found following function(s): " + funcs;
|
answ.message = " Module " + oPayload.id + " successfully stored! Found following function(s): " + funcs;
|
||||||
oPayload.functions = JSON.stringify(funcs);
|
oPayload.functions = JSON.stringify(funcs);
|
||||||
dbMod.storeModule(user.username, oPayload);
|
dbMod.storeModule(user.username, oPayload);
|
||||||
|
|
|
||||||
|
|
@ -53,27 +53,22 @@ Dynamic Modules
|
||||||
})(this);
|
})(this);
|
||||||
|
|
||||||
issueApiCall = function(logger) {
|
issueApiCall = function(logger) {
|
||||||
return function(method, url, credentials, cb) {
|
return function(method, url, data, options, cb) {
|
||||||
var err, func;
|
var err;
|
||||||
try {
|
try {
|
||||||
if (method === 'get') {
|
return needle.request(method, url, data, options, (function(_this) {
|
||||||
func = needle.get;
|
|
||||||
} else {
|
|
||||||
func = needle.post;
|
|
||||||
}
|
|
||||||
return func(url, credentials, (function(_this) {
|
|
||||||
return function(err, resp, body) {
|
return function(err, resp, body) {
|
||||||
try {
|
try {
|
||||||
return cb(err, resp, body);
|
return cb(err, resp, body);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
err = _error;
|
err = _error;
|
||||||
return logger('Error during apicall! ' + err.message);
|
return logger('Error during needle request! ' + err.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})(this));
|
})(this));
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
err = _error;
|
err = _error;
|
||||||
return logger('Error before apicall! ' + err.message);
|
return logger('Error before needle request! ' + err.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -114,7 +109,7 @@ Dynamic Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fTryToLoad = function(params) {
|
fTryToLoad = function(params) {
|
||||||
var logFunc, oDecrypted, sandbox;
|
var logFunc, msg, oDecrypted, sandbox;
|
||||||
if (params) {
|
if (params) {
|
||||||
try {
|
try {
|
||||||
oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey);
|
oDecrypted = cryptico.decrypt(params, _this.oPrivateRSAkey);
|
||||||
|
|
@ -132,8 +127,9 @@ Dynamic Modules
|
||||||
sandbox = {
|
sandbox = {
|
||||||
id: userId + '.' + modId + '.vm',
|
id: userId + '.' + modId + '.vm',
|
||||||
params: params,
|
params: params,
|
||||||
apicall: issueApiCall(logFunc),
|
needlereq: issueApiCall(logFunc),
|
||||||
log: logFunc,
|
log: logFunc,
|
||||||
|
debug: console.log,
|
||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
|
|
@ -141,7 +137,11 @@ Dynamic Modules
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
err = _error;
|
err = _error;
|
||||||
answ.code = 400;
|
answ.code = 400;
|
||||||
answ.message = 'Loading Module failed: ' + err.message;
|
msg = err.message;
|
||||||
|
if (!msg) {
|
||||||
|
msg = 'Try to run the script locally to track the error! Sadly we cannot provide the line number';
|
||||||
|
}
|
||||||
|
answ.message = 'Loading Module failed: ' + msg;
|
||||||
}
|
}
|
||||||
return cb({
|
return cb({
|
||||||
answ: answ,
|
answ: answ,
|
||||||
|
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* EmailYak EVENT MODULE
|
|
||||||
*/
|
|
||||||
|
|
||||||
var credentials = null;
|
|
||||||
|
|
||||||
function loadCredentials(cred) {
|
|
||||||
if(!cred || !cred.key) {
|
|
||||||
console.error('ERROR in EmailYak EM: credentials file corrupt');
|
|
||||||
} else {
|
|
||||||
credentials = cred;
|
|
||||||
console.log('Successfully loaded EmailYak EM credentials');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME every second mail gets lost?
|
|
||||||
// 1) for http.request options, set Connection:keep-alive
|
|
||||||
// 2) set Agent.maxSockets = 1024 (so more connection to play around
|
|
||||||
// with )
|
|
||||||
// 3) very critical: DO a timeout for the http.request.
|
|
||||||
//
|
|
||||||
// e.g.
|
|
||||||
// var responseHdr = function (clientResponse) {
|
|
||||||
// if (clientResposne) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// clientRequest.abort();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// var timeoutHdr = setTimeout(function() {
|
|
||||||
// clientRequest.emit('req-timeout');
|
|
||||||
// }, 5000); // timeout after 5 secs
|
|
||||||
//
|
|
||||||
// clientRequest.on("req-timeout", responseHdr);
|
|
||||||
// clientRequest.on('error', function(e) {
|
|
||||||
// clearTimeout(timeoutHdr);
|
|
||||||
// console.error('Ok.. clientrequest error' + myCounter);
|
|
||||||
// next({err:JSON.stringify(e)});
|
|
||||||
// });
|
|
||||||
function newMail(callback) { //FIXME not beautiful to have to set prop each time here
|
|
||||||
needle.get('https://api.emailyak.com/v1/' + credentials.key + '/json/get/new/email/',
|
|
||||||
function (error, response, body){
|
|
||||||
if (!error && response.statusCode == 200) {
|
|
||||||
var mails = JSON.parse(body).Emails;
|
|
||||||
for(var i = 0; i < mails.length; i++) callback(mails[i]);
|
|
||||||
} else console.error('ERROR in EmailYak EM newMail: ' + error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.loadCredentials = loadCredentials;
|
|
||||||
exports.newMail = newMail;
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"id": "rule_1",
|
|
||||||
"event": "mail",
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"module": "probinder->newContent",
|
|
||||||
"arguments": {
|
|
||||||
"content": "Rule#1: $X.subject"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "rule_2",
|
|
||||||
"event": "mail",
|
|
||||||
"condition": { "sender": "sender2" },
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"module": "probinder->newContent",
|
|
||||||
"arguments": {
|
|
||||||
"content": "Rule#2: $X.subject"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "rule_emailyak",
|
|
||||||
"event": "yakmail",
|
|
||||||
"condition": { "FromAddress": "dominic.bosch.db@gmail.com" },
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"module": "probinder->newContent",
|
|
||||||
"arguments": {
|
|
||||||
"content": "Received from EmailYak: $X.textbody"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "rule_pull_emailyak",
|
|
||||||
"event": "emailyak->newMail",
|
|
||||||
"condition": { "FromAddress": "dominic.bosch.db@gmail.com" },
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"module": "probinder->newContent",
|
|
||||||
"arguments": {
|
|
||||||
"content": "Received from EmailYak: $X.textbody"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "rule_pull_probinder",
|
|
||||||
"event": "probinder->unread",
|
|
||||||
"condition": { "serviceId": "32" },
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"module": "probinder->makeFileEntry",
|
|
||||||
"arguments": {
|
|
||||||
"service": "$X.serviceId",
|
|
||||||
"id": "$X.id"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"module": "probinder->setRead",
|
|
||||||
"arguments": {
|
|
||||||
"id": "$X.id"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -16,7 +16,7 @@ fOnLoad = () ->
|
||||||
# editor.session.setUseSoftTabs false
|
# editor.session.setUseSoftTabs false
|
||||||
|
|
||||||
document.title = 'Rule Forge!'
|
document.title = 'Rule Forge!'
|
||||||
$( '#pagetitle' ).text '{{{user.username}}}, forge your rule!'
|
$( '#pagetitle' ).text '{{{user.username}}}, forge your ECA Rule!'
|
||||||
|
|
||||||
# Fetch Event Poller user-specific parameters
|
# Fetch Event Poller user-specific parameters
|
||||||
fFetchEventParams = ( name ) ->
|
fFetchEventParams = ( name ) ->
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
editor.getSession().setMode("ace/mode/json");
|
editor.getSession().setMode("ace/mode/json");
|
||||||
editor.setShowPrintMargin(false);
|
editor.setShowPrintMargin(false);
|
||||||
document.title = 'Rule Forge!';
|
document.title = 'Rule Forge!';
|
||||||
$('#pagetitle').text('{{{user.username}}}, forge your rule!');
|
$('#pagetitle').text('{{{user.username}}}, forge your ECA Rule!');
|
||||||
fFetchEventParams = function(name) {
|
fFetchEventParams = function(name) {
|
||||||
var arr, obj;
|
var arr, obj;
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title></title>
|
<title></title>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Roboto:300' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Nunito' rel='stylesheet' type='text/css'>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
<script src='//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||||
<script type='text/javascript'>
|
<script type='text/javascript'>
|
||||||
var checkIncludes = function () {
|
var checkIncludes = function () {
|
||||||
if( window.$ === undefined ) {
|
if( window.$ === undefined ) {
|
||||||
|
|
@ -23,6 +25,7 @@
|
||||||
{{{menubar}}}
|
{{{menubar}}}
|
||||||
<div id="info"></div>
|
<div id="info"></div>
|
||||||
<div id="mainbody">
|
<div id="mainbody">
|
||||||
|
<p></p>
|
||||||
<div id="pagetitle"></div>
|
<div id="pagetitle"></div>
|
||||||
{{{content}}}
|
{{{content}}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,38 +7,147 @@ Action Invoker Name: <input id="input_id" type="text" />
|
||||||
<tr>
|
<tr>
|
||||||
<td id="editor_col" valign="top">
|
<td id="editor_col" valign="top">
|
||||||
<div id="editor">
|
<div id="editor">
|
||||||
#
|
###
|
||||||
# ProBinder Action Invoker
|
ProBinder ACTION INVOKER
|
||||||
#
|
------------------------
|
||||||
# Action Invoker requires user params:
|
|
||||||
# - username: The ProBinder login username
|
Global variables
|
||||||
# - password: The ProBinder login password
|
This module requires user-specific parameters:
|
||||||
#
|
- username
|
||||||
|
- password
|
||||||
|
- companyId: company where to post the binder entries
|
||||||
|
- contextId: context where to post the binder entries
|
||||||
|
###
|
||||||
|
urlService = 'https://probinder.com/service/'
|
||||||
|
credentials =
|
||||||
|
username: params.username
|
||||||
|
password: params.password
|
||||||
|
|
||||||
#
|
#
|
||||||
# createBinderEntry function requires arguments:
|
# The standard callback can be used if callback is not provided, e.g. if
|
||||||
|
# the function is called from outside
|
||||||
#
|
#
|
||||||
# - company: The ProBidner company of the binder
|
standardCallback = ( funcName ) ->
|
||||||
# - context: The ProBinder context (the binder ID)
|
( err, resp, body ) ->
|
||||||
#
|
|
||||||
exports.createBinderEntry = ( evt ) ->
|
|
||||||
url = 'https://probinder.com/service/27/save'
|
|
||||||
|
|
||||||
credentials =
|
|
||||||
username: params.username
|
|
||||||
password: params.password
|
|
||||||
|
|
||||||
data =
|
|
||||||
companyId: evt.company
|
|
||||||
context: evt.context
|
|
||||||
text: evt.content
|
|
||||||
|
|
||||||
needle.post url, data, credentials, ( err, resp, body ) ->
|
|
||||||
if err
|
if err
|
||||||
log err
|
log "ERROR: During function '#{ funcName }'"
|
||||||
if resp.statusCode isnt 200
|
else
|
||||||
log 'Request not successful:'
|
if resp.statusCode is 200
|
||||||
log body
|
log "Function '#{ funcName }' ran through without error"
|
||||||
|
else
|
||||||
|
log "ERROR: During function '#{ funcName }': #{ body.error.message }"
|
||||||
|
|
||||||
|
###
|
||||||
|
Call the ProBinder service with the given parameters.
|
||||||
|
|
||||||
|
@param {Object} args the required function arguments object
|
||||||
|
@param {Object} [args.data] the data to be posted
|
||||||
|
@param {String} args.service the required service identifier to be appended to the url
|
||||||
|
@param {String} args.method the required method identifier to be appended to the url
|
||||||
|
@param {function} [args.callback] the function to receive the request answer
|
||||||
|
###
|
||||||
|
exports.call = ( args ) ->
|
||||||
|
if not args.service or not args.method
|
||||||
|
log 'ERROR in call function: Missing arguments!'
|
||||||
|
else
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'call'
|
||||||
|
url = urlService + args.service + '/' + args.method
|
||||||
|
needlereq 'post', url, args.data, credentials, args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Calls the user's unread content service.
|
||||||
|
|
||||||
|
@param {Object} [args] the optional object containing the callback function
|
||||||
|
@param {function} [args.callback] refer to call function
|
||||||
|
###
|
||||||
|
exports.getUnreadContents = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'getUnreadContents'
|
||||||
|
exports.call
|
||||||
|
service: '36'
|
||||||
|
method: 'unreadcontent'
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Calls the content get service with the content id and the service id provided.
|
||||||
|
|
||||||
|
@param {Object} args the object containing the service id and the content id,
|
||||||
|
success and error callback methods
|
||||||
|
@param {String} args.serviceid the service id that is able to process this content
|
||||||
|
@param {String} args.contentid the content id
|
||||||
|
@param {function} [args.callback] receives the needle answer from the "call" function
|
||||||
|
###
|
||||||
|
exports.getContent = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'getContent'
|
||||||
|
exports.call
|
||||||
|
service: '2'
|
||||||
|
method: 'get'
|
||||||
|
data:
|
||||||
|
id: args.contentid
|
||||||
|
service: args.serviceid
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
Does everything to post something in a binder
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.content the content to be posted
|
||||||
|
###
|
||||||
|
exports.newContent = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'newContent'
|
||||||
|
exports.call
|
||||||
|
service: '27'
|
||||||
|
method: 'save'
|
||||||
|
data:
|
||||||
|
companyId: params.companyId
|
||||||
|
context: params.contextId
|
||||||
|
text: args.content
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Does everything to post a file info in a binder tabe
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.service the content service
|
||||||
|
@param {String} args.id the content id
|
||||||
|
###
|
||||||
|
exports.makeFileEntry = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'makeFileEntry'
|
||||||
|
exports.getContent
|
||||||
|
serviceid: args.service
|
||||||
|
contentid: args.id
|
||||||
|
callback: ( err, resp, body ) ->
|
||||||
|
exports.call
|
||||||
|
service: '27'
|
||||||
|
method: 'save'
|
||||||
|
data:
|
||||||
|
companyId: params.companyId
|
||||||
|
context: params.contextId
|
||||||
|
text: "New file (#{ body.title }) in tab \"#{ body.context[0].name }\",
|
||||||
|
find it <a href=\"https://probinder.com/file/#{ body.fileIds[0] }\">here</a>!'"
|
||||||
|
callback: args.callback
|
||||||
|
|
||||||
|
###
|
||||||
|
Sets the content as read.
|
||||||
|
|
||||||
|
@param {Object} args the object containing the content
|
||||||
|
@param {String} args.content the content to be posted
|
||||||
|
###
|
||||||
|
exports.setRead = ( args ) ->
|
||||||
|
if not args.callback
|
||||||
|
args.callback = standardCallback 'setRead'
|
||||||
|
exports.call
|
||||||
|
service: '2'
|
||||||
|
method: 'setread'
|
||||||
|
data:
|
||||||
|
id: args.id
|
||||||
|
callback: args.callback
|
||||||
</div>
|
</div>
|
||||||
<button id="but_submit">save</button>
|
<button id="but_submit">save</button>
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -53,6 +162,14 @@ This action invoker requires user-specific properties:
|
||||||
<td><img src="red_cross_small.png"></td>
|
<td><img src="red_cross_small.png"></td>
|
||||||
<td><input type="text" value="password" /></td>
|
<td><input type="text" value="password" /></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="red_cross_small.png"></td>
|
||||||
|
<td><input type="text" value="companyId" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="red_cross_small.png"></td>
|
||||||
|
<td><input type="text" value="contextId" /></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="red_cross_small.png"></td>
|
<td><img src="red_cross_small.png"></td>
|
||||||
<td><input type="text" /></td>
|
<td><input type="text" /></td>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ Event Poller Name: <input id="input_id" type="text" />
|
||||||
<div id="editor">
|
<div id="editor">
|
||||||
#
|
#
|
||||||
# EmailYak EVENT POLLER
|
# EmailYak EVENT POLLER
|
||||||
|
# ---------------------
|
||||||
#
|
#
|
||||||
# Requires user params:
|
# Requires user params:
|
||||||
# - apikey: The user's EmailYak API key
|
# - apikey: The user's EmailYak API key
|
||||||
|
|
@ -17,13 +18,19 @@ Event Poller Name: <input id="input_id" type="text" />
|
||||||
url = 'https://api.emailyak.com/v1/' + params.apikey + '/json/get/new/email/'
|
url = 'https://api.emailyak.com/v1/' + params.apikey + '/json/get/new/email/'
|
||||||
|
|
||||||
exports.newMail = ( pushEvent ) ->
|
exports.newMail = ( pushEvent ) ->
|
||||||
needle.get url, ( err, resp, body ) ->
|
|
||||||
if not err and resp.statusCode is 200
|
|
||||||
mails = JSON.parse( body ).Emails
|
|
||||||
pushEvent mail for mail in mails
|
|
||||||
else
|
|
||||||
log.error 'Error in EmailYak EM newMail: ' + err.message
|
|
||||||
|
|
||||||
|
# needlereq allows the user to make calls to API's
|
||||||
|
# Refer to https://github.com/tomas/needle for more information
|
||||||
|
#
|
||||||
|
# Syntax: needle.request method, url, data, [options], callback
|
||||||
|
#
|
||||||
|
needlereq 'get', url, null, null, ( err, resp, body ) ->
|
||||||
|
if err
|
||||||
|
log 'Error in EmailYak EM newMail: ' + err.message
|
||||||
|
else
|
||||||
|
if resp.statusCode is 200
|
||||||
|
mails = JSON.parse( body ).Emails
|
||||||
|
pushEvent mail for mail in mails
|
||||||
</div>
|
</div>
|
||||||
<button id="but_submit">save</button>
|
<button id="but_submit">save</button>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
fCreateLink( 'Edit Modules',
|
fCreateLink( 'Edit Modules',
|
||||||
fRedirect( 'forge?page=edit_modules' )
|
fRedirect( 'forge?page=edit_modules' )
|
||||||
);
|
);
|
||||||
fCreateLink( 'Edit rules',
|
fCreateLink( 'Edit Rules',
|
||||||
fRedirect( 'forge?page=edit_rules' )
|
fRedirect( 'forge?page=edit_rules' )
|
||||||
);
|
);
|
||||||
// fCreateLink( 'admin', fRedirect( 'admin' ) );
|
// fCreateLink( 'admin', fRedirect( 'admin' ) );
|
||||||
|
|
|
||||||
61
webpages/public/index.html
Normal file
61
webpages/public/index.html
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Roboto:300' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Nunito' rel='stylesheet' type='text/css'>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js' type='text/javascript'></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="menubar">
|
||||||
|
<script>
|
||||||
|
var menubar = $( '#menubar' );
|
||||||
|
|
||||||
|
var fRedirect = function( url ) {
|
||||||
|
return function() {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fCreateLink = function( text, fAction ) {
|
||||||
|
var link = $( '<div>' ).text( text );
|
||||||
|
link.click( fAction );
|
||||||
|
menubar.append(link);
|
||||||
|
};
|
||||||
|
|
||||||
|
fCreateLink( 'Forge Event Poller',
|
||||||
|
fRedirect( 'forge?page=forge_event_poller' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Forge Action Invoker',
|
||||||
|
fRedirect( 'forge?page=forge_action_invoker' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Forge Rule',
|
||||||
|
fRedirect( 'forge?page=forge_rule' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Invoke Event',
|
||||||
|
fRedirect( 'forge?page=forge_event' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Edit Modules',
|
||||||
|
fRedirect( 'forge?page=edit_modules' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Edit Rules',
|
||||||
|
fRedirect( 'forge?page=edit_rules' )
|
||||||
|
);
|
||||||
|
fCreateLink( 'Logout', function() {
|
||||||
|
$.post( '/logout' ).done( fRedirect( document.URL ) );
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="info"></div>
|
||||||
|
<div id="mainbody">
|
||||||
|
<p></p>
|
||||||
|
|
||||||
|
<div id="pagetitle">Welcome to the WebAPI ECA-Engine!</div>
|
||||||
|
<p>
|
||||||
|
Enjoy creating your own ECA rules, together with the required action invoker modules!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif, "Times New Roman", Georgia, Serif;
|
font-family: 'Roboto', sans-serif, "Times New Roman", Georgia, Serif;
|
||||||
font-size: 80%;
|
/*font-size: 0.9em;*/
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
background-color: #EEF;
|
background-color: #EEF;
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ input[type=text]:focus {
|
||||||
}
|
}
|
||||||
|
|
||||||
#pagetitle {
|
#pagetitle {
|
||||||
font-size: 1.5em;
|
font-size: 2em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue