initial commit of slack bot
This commit is contained in:
1 parent
631a702499
commit
3574ee7d59
13 files changed
+311
-8
No files matched your search
@@ -682,6 +682,13 @@
|
||||
"fileName": "DiscordBot.js",
|
||||
"folderName": "Trading-Bot/Announcements"
|
||||
},
|
||||
{
|
||||
"name": "Slack Bot",
|
||||
"propertyName": "slackBot",
|
||||
"functionName": "newSuperalgosBotModulesSlackBot",
|
||||
"fileName": "SlackBot.js",
|
||||
"folderName": "Trading-Bot/Announcements"
|
||||
},
|
||||
{
|
||||
"name": "Trading Process",
|
||||
"propertyName": "tradingProcess",
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 270 270" style="enable-background:new 0 0 270 270;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#E01E5A;}
|
||||
.st1{fill:#36C5F0;}
|
||||
.st2{fill:#2EB67D;}
|
||||
.st3{fill:#ECB22E;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M99.4,151.2c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h12.9V151.2z"/>
|
||||
<path class="st0" d="M105.9,151.2c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v32.3c0,7.1-5.8,12.9-12.9,12.9
|
||||
s-12.9-5.8-12.9-12.9V151.2z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M118.8,99.4c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9s12.9,5.8,12.9,12.9v12.9H118.8z"/>
|
||||
<path class="st1" d="M118.8,105.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9H86.5c-7.1,0-12.9-5.8-12.9-12.9
|
||||
s5.8-12.9,12.9-12.9H118.8z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st2" d="M170.6,118.8c0-7.1,5.8-12.9,12.9-12.9c7.1,0,12.9,5.8,12.9,12.9s-5.8,12.9-12.9,12.9h-12.9V118.8z"/>
|
||||
<path class="st2" d="M164.1,118.8c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9V86.5c0-7.1,5.8-12.9,12.9-12.9
|
||||
c7.1,0,12.9,5.8,12.9,12.9V118.8z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M151.2,170.6c7.1,0,12.9,5.8,12.9,12.9c0,7.1-5.8,12.9-12.9,12.9c-7.1,0-12.9-5.8-12.9-12.9v-12.9H151.2z"/>
|
||||
<path class="st3" d="M151.2,164.1c-7.1,0-12.9-5.8-12.9-12.9c0-7.1,5.8-12.9,12.9-12.9h32.3c7.1,0,12.9,5.8,12.9,12.9
|
||||
c0,7.1-5.8,12.9-12.9,12.9H151.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"type": "Slack Bot",
|
||||
"editors": {
|
||||
"config": true
|
||||
},
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure",
|
||||
"actionFunction": "uiObject.configEditor.activate",
|
||||
"label": "Configure",
|
||||
"iconPathOn": "configuration",
|
||||
"iconPathOff": "configuration"
|
||||
},
|
||||
{
|
||||
"action": "Send Slack Test Message",
|
||||
"label": "Send Slack Test Message",
|
||||
"iconPathOn": "test-entity",
|
||||
"iconPathOff": "test-entity",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"label": "Delete",
|
||||
"iconPathOn": "delete-entity",
|
||||
"iconPathOff": "delete-entity",
|
||||
"actionFunction": "payload.executeAction"
|
||||
}
|
||||
],
|
||||
"initialValues": {
|
||||
"config": "{\n\"webhookURL\": \"https://hooks.slack.com/services/abc/abc/abc\"\n}"
|
||||
},
|
||||
"addLeftIcons": true,
|
||||
"level": 3,
|
||||
"attachingRules": {
|
||||
"compatibleTypes": "->Social Bots->"
|
||||
},
|
||||
"childrenNodesProperties": [],
|
||||
"propertyNameAtParent": "slackBots"
|
||||
}
|
||||
@@ -13,6 +13,12 @@
|
||||
"relatedUiObject": "Discord Bot",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"label": "Add Slack Bot",
|
||||
"relatedUiObject": "Slack Bot",
|
||||
"actionFunction": "payload.executeAction"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
@@ -40,6 +46,12 @@
|
||||
"type": "array",
|
||||
"childType": "Discord Bot",
|
||||
"autoAdd": true
|
||||
},
|
||||
{
|
||||
"name": "slackBots",
|
||||
"type": "array",
|
||||
"childType": "Slack Bot",
|
||||
"autoAdd": true
|
||||
}
|
||||
],
|
||||
"propertyNameAtParent": "socialBots"
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"type": "Discord Bot",
|
||||
"definition": {
|
||||
"text": "The Discord Bot node is used for defining the configuration for a Discord Bot. This bot allows Superalgos to send announcements to a Discord Channel.",
|
||||
"updated": 1619546769461
|
||||
},
|
||||
"paragraphs": [
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "In order to use the Discord Bot, you will need to create a new Webhook Integration in Discord. The only configuration that is required within Superalgos is the webhookURL.",
|
||||
"updated": 1619546875758
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Parameters:"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "- webhookURL - required - obtained from Integrations > Webhooks in the channel settings."
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "- format - optional - allows custom formatting of the message being sent into Discord."
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Recognized Format Variables:"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "- `%{EXCHANGE}` the exchange which is operating, i.e. Binance"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "- `%{MARKET}` the market which is operating. i.e. BTC/USDT"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "- `%{MESSAGE}` the text being sent"
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "An example format is:"
|
||||
},
|
||||
{
|
||||
"style": "Javascript",
|
||||
"text": "\"%{EXCHANGE} %{MARKET}: %{MESSAGE}\""
|
||||
},
|
||||
{
|
||||
"style": "Text",
|
||||
"text": "Which results in a final message in Discord that looks like:"
|
||||
},
|
||||
{
|
||||
"style": "Javascript",
|
||||
"text": "\"Binance BTC/USDT: Backtesting Session 'Lightning Strike' is starting.\""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
},
|
||||
{
|
||||
"style": "Note",
|
||||
"text": "At present Superalgos only supports Telegram and Discord messaging applications.",
|
||||
"text": "At present Superalgos only supports Telegram, Discord, and Slack messaging applications.",
|
||||
"updated": 1619547181067
|
||||
}
|
||||
],
|
||||
@@ -16,4 +16,4 @@
|
||||
"text": "A Social Bots node is used to define the bots for each messaging application. These messaging bots are used to send announcements and receive commands used to interact with Superalgos.",
|
||||
"updated": 1618222853055
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
exports.newSuperalgosBotModulesSlackBot = function (processIndex) {
|
||||
|
||||
const MODULE_NAME = 'Slack Bot'
|
||||
|
||||
let thisObject = {
|
||||
webhookURL: undefined,
|
||||
taskParameters: undefined,
|
||||
format: undefined,
|
||||
sendMessage: sendMessage,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize(config) {
|
||||
/* Slack Bot Initialization */
|
||||
|
||||
try {
|
||||
thisObject.webhookURL = config.webhookURL
|
||||
thisObject.taskParameters = {
|
||||
exchange: TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.name,
|
||||
market: TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName +
|
||||
'/' +
|
||||
TS.projects.superalgos.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName
|
||||
}
|
||||
if (config.format === undefined) {
|
||||
thisObject.format = "%{MESSAGE}"
|
||||
} else {
|
||||
thisObject.format = config.format
|
||||
}
|
||||
} catch (err) {
|
||||
logError("initialize -> err = " + err.stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function finalize() {}
|
||||
|
||||
function sendMessage(message) {
|
||||
const https = require('https')
|
||||
|
||||
try {
|
||||
message = formatMessage(message)
|
||||
message = JSON.stringify({text: message})
|
||||
} catch (err) {
|
||||
logError("announce -> Slack JSON message error -> err = " + err)
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
}
|
||||
|
||||
const req = https.request(thisObject.webhookURL, requestOptions, (res) => {
|
||||
let response = ''
|
||||
res.on('data', (data) => { response += data })
|
||||
res.on('end', () => { resolve(response) })
|
||||
})
|
||||
|
||||
req.on('error', (err) => {
|
||||
reject(err)
|
||||
logWarn("announce -> Slack request error -> err = " + err)
|
||||
})
|
||||
|
||||
req.write(message)
|
||||
req.end()
|
||||
})
|
||||
}
|
||||
|
||||
function formatMessage(message) {
|
||||
formattedMessage = thisObject.format
|
||||
formattedMessage = formattedMessage.replace('%{EXCHANGE}', thisObject.taskParameters.exchange)
|
||||
formattedMessage = formattedMessage.replace('%{MARKET}', thisObject.taskParameters.market)
|
||||
formattedMessage = formattedMessage.replace('%{MESSAGE}', message)
|
||||
return formattedMessage
|
||||
}
|
||||
|
||||
function logWarn(message) {
|
||||
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[WARN] ' + message)
|
||||
}
|
||||
|
||||
function logError(message) {
|
||||
TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[ERROR] ' + message)
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,10 @@ exports.newSuperalgosBotModulesSocialBots = function (processIndex) {
|
||||
let config = socialBot.config
|
||||
socialBot.botInstance = TS.projects.superalgos.botModules.discordBot.newSuperalgosBotModulesDiscordBot(processIndex)
|
||||
socialBot.botInstance.initialize(config)
|
||||
} else if (socialBot.type === "Slack Bot") {
|
||||
let config = socialBot.config
|
||||
socialBot.botInstance = TS.projects.superalgos.botModules.slackBot.newSuperalgosBotModulesSlackBot(processIndex)
|
||||
socialBot.botInstance.initialize(config)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +42,7 @@ exports.newSuperalgosBotModulesSocialBots = function (processIndex) {
|
||||
try {
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, text).catch(err => TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
} else if (socialBot.type === "Discord Bot") {
|
||||
} else if (socialBot.type === "Discord Bot" ||socialBot.type === "Slack Bot" ) {
|
||||
socialBot.botInstance.sendMessage(text).catch(err => TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Discord Bot error -> err = " + err))
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -61,7 +65,7 @@ exports.newSuperalgosBotModulesSocialBots = function (processIndex) {
|
||||
if (TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop] !== undefined) {
|
||||
for (let i = 0; i < TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop].length; i++) {
|
||||
let socialBot = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop][i]
|
||||
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot") {
|
||||
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot") {
|
||||
socialBot.botInstance.finalize()
|
||||
}
|
||||
}
|
||||
@@ -77,7 +81,7 @@ exports.newSuperalgosBotModulesSocialBots = function (processIndex) {
|
||||
if (TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop] !== undefined) {
|
||||
for (let i = 0; i < TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop].length; i++) {
|
||||
let socialBot = TS.projects.superalgos.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop][i]
|
||||
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot") {
|
||||
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot") {
|
||||
socialBot.botInstance.sendMessage(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,6 +722,11 @@ function newSuperalgosActionSwitch() {
|
||||
UI.projects.superalgos.functionLibraries.socialBotsFunctions.sendDiscordTestMessage(action.node, action.callBackFunction)
|
||||
}
|
||||
break
|
||||
case 'Send Slack Test Message':
|
||||
{
|
||||
UI.projects.superalgos.functionLibraries.socialBotsFunctions.sendSlackTestMessage(action.node, action.callBackFunction)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ function newSuperalgosFunctionLibraryLearningSessionFunctions() {
|
||||
'Back Learning Session->Live Learning Session->' +
|
||||
'Learning Parameters->' +
|
||||
'Learning Algorithm->Time Range->Time Frame->Heartbeats->User Defined Parameters->' +
|
||||
'Social Bots->Telegram Bot->Discord Bot->'
|
||||
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->'
|
||||
|
||||
let session = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
function newSuperalgosFunctionLibrarySocialBotsFunctions() {
|
||||
thisObject = {
|
||||
sendTelegramTestMessage: sendTelegramTestMessage,
|
||||
sendDiscordTestMessage: sendDiscordTestMessage
|
||||
sendDiscordTestMessage: sendDiscordTestMessage,
|
||||
sendSlackTestMessage: sendSlackTestMessage
|
||||
}
|
||||
|
||||
return thisObject
|
||||
@@ -127,4 +128,59 @@ function newSuperalgosFunctionLibrarySocialBotsFunctions() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sendSlackTestMessage(node, callBackFunction) {
|
||||
|
||||
let webhookURL = UI.projects.superalgos.utilities.nodeConfig.loadPropertyFromNodeConfig(node.payload, 'webhookURL')
|
||||
|
||||
if (webhookURL === undefined) {
|
||||
node.payload.uiObject.setErrorMessage('webhookURL parameter not defined.')
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
|
||||
let message = "Test message from Superalgos!"
|
||||
|
||||
httpRequestJSON(JSON.stringify({text: message}), webhookURL, onResponse)
|
||||
|
||||
function onResponse(err) {
|
||||
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
node.payload.uiObject.setInfoMessage('Slack message sent.')
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
} else {
|
||||
node.payload.uiObject.setErrorMessage('Could not send Slack message. Error Response: ' + err.message)
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function httpRequestJSON(pContentToSend, pPath, callBackFunction) {
|
||||
let xmlHttpRequest = new XMLHttpRequest();
|
||||
xmlHttpRequest.onreadystatechange = function () {
|
||||
if (this.readyState === 4 && this.status === 200) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, xmlHttpRequest.responseText);
|
||||
return;
|
||||
} else if (this.readyState === 4 && (this.status === 404 || this.status === 401 || this.status === 400)) {
|
||||
callBackFunction({
|
||||
result: "Fail",
|
||||
message: xmlHttpRequest.responseText
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if (pContentToSend === undefined) {
|
||||
xmlHttpRequest.open("GET", pPath, true);
|
||||
xmlHttpRequest.send();
|
||||
} else {
|
||||
try {
|
||||
let blob = new Blob([pContentToSend]);
|
||||
xmlHttpRequest.open("POST", pPath, true);
|
||||
xmlHttpRequest.send(blob);
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[ERROR] callServer -> err.message = " & err.message); }
|
||||
callBackFunction({ result: "Fail", message: err.message })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ function newSuperalgosFunctionLibraryTradingSessionFunctions() {
|
||||
'Backtesting Session->Paper Trading Session->Forward Testing Session->Live Trading Session->' +
|
||||
'Trading Parameters->' +
|
||||
'Session Base Asset->Session Quoted Asset->Time Range->Time Frame->Slippage->Fee Structure->Snapshots->Heartbeats->User Defined Parameters->' +
|
||||
'Social Bots->Telegram Bot->Discord Bot->' +
|
||||
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->' +
|
||||
'Exchange Account Asset->Asset->'
|
||||
|
||||
let session = UI.projects.superalgos.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
|
||||
|
||||
Reference in new issue
Block a user