Merge pull request #1932 from ssplatt/twitter-announce-bot

[WIP] Twitter announce bot
This commit is contained in:
Luis Fernando Molina authored and GitHub committed 2021-09-30 16:40:06 -04:00
commit 4b81270699
16 files changed
+5225 -31

No files matched your search

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
<style type="text/css">
.st0{fill:#1D9BF0;}
</style>
<g id="Logo_1_">
<path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -19,6 +19,12 @@
"relatedUiObject": "Slack Bot",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"label": "Add Twitter Bot",
"relatedUiObject": "Twitter Bot",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"askConfirmation": true,
@@ -52,6 +58,12 @@
"type": "array",
"childType": "Slack Bot",
"autoAdd": true
},
{
"name": "twitterBots",
"type": "array",
"childType": "Twitter Bot",
"autoAdd": true
}
],
"propertyNameAtParent": "socialBots"
@@ -0,0 +1,41 @@
{
"type": "Twitter Bot",
"editors": {
"config": true
},
"menuItems": [
{
"action": "Configure",
"actionFunction": "uiObject.configEditor.activate",
"label": "Configure",
"iconPathOn": "configuration",
"iconPathOff": "configuration"
},
{
"action": "Send Twitter Test Message",
"label": "Send Twitter 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 \"consumer_key\": \"TWITTER_CONSUMER_KEY\"\n \"consumer_secret\": \"TWITTER_CONSUMER_SECRET\"\n \"access_token_key\": \"TWITTER_ACCESS_TOKEN_KEY\"\n \"access_token_secret\": \"TWITTER_ACCESS_TOKEN_SECRET\"\n}"
},
"addLeftIcons": true,
"level": 3,
"attachingRules": {
"compatibleTypes": "->Social Bots->"
},
"childrenNodesProperties": [],
"propertyNameAtParent": "TwitterBots"
}
@@ -27,6 +27,9 @@ exports.newFoundationsBotModulesSocialBots = function (processIndex) {
} else if (socialBot.type === "Slack Bot") {
socialBot.botInstance = TS.projects.foundations.botModules.slackBot.newFoundationsBotModulesSlackBot(processIndex)
socialBot.botInstance.initialize(config)
} else if (socialBot.type === "Twitter Bot") {
socialBot.botInstance = TS.projects.foundations.botModules.twitterBot.newFoundationsBotModulesTwitterBot(processIndex)
socialBot.botInstance.initialize(config)
}
}
}
@@ -41,8 +44,8 @@ exports.newFoundationsBotModulesSocialBots = function (processIndex) {
try {
if (socialBot.type === "Telegram Bot") {
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, text).catch(err => TS.projects.foundations.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" ||socialBot.type === "Slack Bot" ) {
socialBot.botInstance.sendMessage(text).catch(err => TS.projects.foundations.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))
} else if (socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot" || socialBot.type === "Twitter Bot" ) {
socialBot.botInstance.sendMessage(text).catch(err => TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> " + socialBot.type + " error -> err = " + err))
}
} catch (err) {
TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> announce -> err = " + err.stack);
@@ -64,7 +67,7 @@ exports.newFoundationsBotModulesSocialBots = function (processIndex) {
if (TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop] !== undefined) {
for (let i = 0; i < TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop].length; i++) {
let socialBot = TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop][i]
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot") {
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot" || socialBot.type === "Twitter Bot") {
socialBot.botInstance.finalize()
}
}
@@ -80,7 +83,7 @@ exports.newFoundationsBotModulesSocialBots = function (processIndex) {
if (TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop] !== undefined) {
for (let i = 0; i < TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop].length; i++) {
let socialBot = TS.projects.foundations.globals.processConstants.CONSTANTS_BY_PROCESS_INDEX_MAP.get(processIndex).SESSION_NODE.socialBots[prop][i]
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot") {
if (socialBot.type === "Telegram Bot" || socialBot.type === "Discord Bot" || socialBot.type === "Slack Bot" || socialBot.type === "Twitter Bot") {
socialBot.botInstance.sendMessage(message)
}
}
@@ -0,0 +1,97 @@
exports.newFoundationsBotModulesTwitterBot = function (processIndex) {
const MODULE_NAME = 'Twitter Bot'
let thisObject = {
taskParameters: undefined,
format: undefined,
twitterclient: undefined,
sendMessage: sendMessage,
initialize: initialize,
finalize: finalize
}
return thisObject
function initialize(config) {
/* Twitter Bot Initialization */
var Twitter = SA.nodeModules.twitter
let consumer_key = config.consumer_key
let consumer_secret = config.consumer_secret
let access_token_key = config.access_token_key
let access_token_secret = config.access_token_secret
if (process.env.TWITTER_CONSUMER_KEY) {
consumer_key = process.env.TWITTER_CONSUMER_KEY
}
if (process.env.TWITTER_CONSUMER_SECRET) {
consumer_secret = process.env.TWITTER_CONSUMER_SECRET
}
if (process.env.TWITTER_ACCESS_TOKEN_KEY) {
access_token_key = process.env.TWITTER_ACCESS_TOKEN_KEY
}
if (process.env.TWITTER_ACCESS_TOKEN_SECRET) {
access_token_secret = process.env.TWITTER_ACCESS_TOKEN_SECRET
}
var twitterclient = new Twitter({
consumer_key: consumer_key,
consumer_secret: consumer_secret,
access_token_key: access_token_key,
access_token_secret: access_token_secret
});
thisObject.twitterclient = twitterclient
try {
thisObject.taskParameters = {
exchange: TS.projects.foundations.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.parentNode.parentNode.name,
market: TS.projects.foundations.globals.taskConstants.TASK_NODE.parentNode.parentNode.parentNode.referenceParent.baseAsset.referenceParent.config.codeName +
'/' +
TS.projects.foundations.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) {
try {
message = formatMessage(message)
message = JSON.stringify({status: message})
} catch (err) {
logError("announce -> Twitter JSON message error -> err = " + err)
}
thisObject.twitterclient.post('statuses/update', message, function(error, tweet, response) {
if(error) throw error;
console.log(tweet); // Tweet body.
console.log(response); // Raw response object.
});
}
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.foundations.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.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, '[ERROR] ' + message)
}
}
@@ -779,6 +779,11 @@ function newFoundationsActionSwitch() {
UI.projects.foundations.functionLibraries.socialBotsFunctions.sendSlackTestMessage(action.node, action.callBackFunction)
}
break
case 'Send Twitter Test Message':
{
UI.projects.foundations.functionLibraries.socialBotsFunctions.sendTwitterTestMessage(action.node, action.callBackFunction)
}
break
case 'Save node to be moved':
{
UI.projects.foundations.spaces.floatingSpace.saveFloatingObjectToBeMoved()
@@ -131,7 +131,7 @@ function newFoundationsFunctionLibraryLearningSessionFunctions() {
'Back Learning Session->Live Learning Session->' +
'Learning Parameters->' +
'Learning Algorithm->Time Range->Time Frame->Heartbeats->User Defined Parameters->' +
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->'
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->Twitter Bot ->'
let session = UI.projects.foundations.functionLibraries.protocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
@@ -2,7 +2,8 @@ function newFoundationsFunctionLibrarySocialBotsFunctions() {
let thisObject = {
sendTelegramTestMessage: sendTelegramTestMessage,
sendDiscordTestMessage: sendDiscordTestMessage,
sendSlackTestMessage: sendSlackTestMessage
sendSlackTestMessage: sendSlackTestMessage,
sendTwitterTestMessage: sendTwitterTestMessage
}
return thisObject
@@ -183,4 +184,43 @@ function newFoundationsFunctionLibrarySocialBotsFunctions() {
}
}
}
function sendTwitterTestMessage(node, callBackFunction) {
var Twitter = SA.nodeModules.twitter
let consumer_key = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'consumer_key')
let consumer_secret = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'consumer_secret')
let access_token_key = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'access_token_key')
let access_token_secret = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'access_token_secret')
if (process.env.TWITTER_CONSUMER_KEY) {
consumer_key = process.env.TWITTER_CONSUMER_KEY
}
if (process.env.TWITTER_CONSUMER_SECRET) {
consumer_secret = process.env.TWITTER_CONSUMER_SECRET
}
if (process.env.TWITTER_ACCESS_TOKEN_KEY) {
access_token_key = process.env.TWITTER_ACCESS_TOKEN_KEY
}
if (process.env.TWITTER_ACCESS_TOKEN_SECRET) {
access_token_secret = process.env.TWITTER_ACCESS_TOKEN_SECRET
}
var twitterclient = new Twitter({
consumer_key: consumer_key,
consumer_secret: consumer_secret,
access_token_key: access_token_key,
access_token_secret: access_token_secret
});
let message = JSON.stringify({status: "Test message from Superalgos!"})
twitterclient.post('statuses/update', message, function(error, tweet, response) {
if(error) {
callBackFunction({ result: "Fail", message: error })
}
console.log(tweet); // Tweet body.
console.log(response); // Raw response object.
});
}
}
@@ -155,7 +155,7 @@ function newFoundationsFunctionLibraryTradingSessionFunctions() {
'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->Slack Bot->' +
'Social Bots->Telegram Bot->Discord Bot->Slack Bot->Twitter Bot->' +
'Social Bot Command->Formula->' +
'Exchange Account Asset->Asset->'
@@ -9223,6 +9223,36 @@
}
}
},
{
"type": "Asset",
"name": "twitter-bot.json",
"config": "{\"codeName\":\"twitter-bot.json\"}",
"project": "Governance",
"assetClasses": [],
"assets": [],
"id": "4cd4da1b-52a1-40f5-a003-a6e72e61e3a0",
"savedPayload": {
"position": {
"x": 36086.17551466609,
"y": 46807.38279050288
},
"targetPosition": {
"x": 36301.75,
"y": 46598.75
},
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
{
"type": "Asset",
"name": "slippage.json",
@@ -12061,4 +12091,4 @@
"isRunning": false
}
}
}
}
@@ -20148,6 +20148,36 @@
}
}
},
{
"type": "Asset",
"name": "twitter-bot.svg",
"config": "{\"codeName\":\"twitter-bot.svg\"}",
"project": "Governance",
"assetClasses": [],
"assets": [],
"id": "8eb55d2d-6f7b-41e9-a550-05eef663e12a",
"savedPayload": {
"position": {
"x": 24465.935573766892,
"y": 46352.57737036275
},
"targetPosition": {
"x": 24580.73569292408,
"y": 46629.74326408255
},
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
{
"type": "Asset",
"name": "slippage.svg",
@@ -23728,4 +23758,4 @@
"isRunning": false
}
}
}
}
@@ -1271,6 +1271,36 @@
}
}
},
{
"type": "Asset",
"name": "TwitterBot.js",
"config": "{\"codeName\":\"TwitterBot.js\"}",
"project": "Governance",
"assetClasses": [],
"assets": [],
"id": "911b9b74-7af1-4865-a527-9f01539632fb",
"savedPayload": {
"position": {
"x": 14288.376537238257,
"y": 47370.32076269797
},
"targetPosition": {
"x": 14074.663708152853,
"y": 47159.781391832774
},
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
{
"type": "Asset",
"name": "SocialBots.js",
@@ -3323,4 +3353,4 @@
"isRunning": false
}
}
}
}
+8 -1
View File
@@ -675,6 +675,13 @@
"fileName": "SlackBot.js",
"folderName": "Trading-Bot/Announcements"
},
{
"name": "Twitter Bot",
"propertyName": "twitterBot",
"functionName": "newFoundationsBotModulesTwitterBot",
"fileName": "TwitterBot.js",
"folderName": "Trading-Bot/Announcements"
},
{
"name": "Trading Process",
"propertyName": "tradingProcess",
@@ -1522,4 +1529,4 @@
]
}
}
]
]
+2 -1
View File
@@ -46,7 +46,8 @@ SA.nodeModules = {
nodeFetch: require('node-fetch'),
ccxt: require('ccxt'),
ccxtMisc: require('./node_modules/ccxt/js/base/functions/misc'),
lookpath: require('lookpath')
lookpath: require('lookpath'),
twitter: require('twitter')
}
run()
+4900 -19
View File
File diff suppressed because it is too large. Load diff
+1
View File
@@ -21,6 +21,7 @@
"path": "^0.12.7",
"simple-git": "^2.45.1",
"telegraf": "^4.4.2",
"twitter": "^1.7.1",
"util": "^0.12.4",
"web3": "^1.5.2",
"ws": "^8.2.1"