Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Commit 1476c0b

Browse files
authored
Merge pull request #1621 from sam-binary/webhook-blocks
Webhook blocks
2 parents 99490d1 + 9ae9ced commit 1476c0b

File tree

6 files changed

+236
-1
lines changed

6 files changed

+236
-1
lines changed

src/botPage/bot/Interface/ToolsInterface.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import CandleInterface from './CandleInterface';
22
import MiscInterface from './MiscInterface';
33
import IndicatorsInterface from './IndicatorsInterface';
4+
import WebhookInterface from './WebhookInterface';
45
import { translate } from '../../../common/i18n';
56

67
// prettier-ignore
78
export default Interface => class extends IndicatorsInterface(
8-
MiscInterface(CandleInterface(Interface))) {
9+
MiscInterface(CandleInterface(WebhookInterface(Interface)))) {
910
getToolsInterface() {
1011
return {
1112
getTime : () => parseInt(new Date().getTime() / 1000),
@@ -76,6 +77,7 @@ export default Interface => class extends IndicatorsInterface(
7677
...this.getCandleInterface(),
7778
...this.getMiscInterface(),
7879
...this.getIndicatorsInterface(),
80+
...this.getWebhookInterface(),
7981
};
8082
}
8183
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { notify } from '../broadcast';
2+
import { translate } from '../../../common/i18n';
3+
4+
export default Interface =>
5+
class extends Interface {
6+
// eslint-disable-next-line class-methods-use-this
7+
sendWebhook(url, payload) {
8+
const onError = () => notify('warn', translate('Unable to send webhook'));
9+
const fetchOption = {
10+
method : 'POST',
11+
mode : 'cors',
12+
headers: { 'Content-Type': 'application/json' },
13+
};
14+
15+
if (payload) {
16+
fetchOption.body = JSON.stringify(payload);
17+
}
18+
19+
fetch(url, fetchOption)
20+
.then(response => {
21+
if (!response.ok) {
22+
onError();
23+
}
24+
})
25+
.catch(onError);
26+
}
27+
28+
getWebhookInterface() {
29+
return {
30+
sendWebhook: this.sendWebhook,
31+
};
32+
}
33+
};

src/botPage/view/blockly/blocks/tools/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ import './block_holder';
77
import './loader';
88
import './candle';
99
import './time';
10+
import './webhook';
11+
import './key_value_pair';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { translate } from '../../../../../common/i18n';
2+
3+
Blockly.Blocks.key_value_pair = {
4+
init() {
5+
this.jsonInit({
6+
message0: translate('Key: %1 Value: %2'),
7+
args0 : [
8+
{
9+
type: 'field_input',
10+
name: 'KEY',
11+
text: 'default',
12+
},
13+
{
14+
type: 'input_value',
15+
name: 'VALUE',
16+
},
17+
],
18+
colour : '#dedede',
19+
output : null,
20+
tooltip: translate('Returns a string representation of a key value pair'),
21+
});
22+
},
23+
};
24+
25+
Blockly.JavaScript.key_value_pair = block => {
26+
const key = block.getFieldValue('KEY') || '';
27+
const value = Blockly.JavaScript.valueToCode(block, 'VALUE', Blockly.JavaScript.ORDER_ATOMIC) || null;
28+
29+
if (!key) {
30+
return '';
31+
}
32+
33+
return [`{"${key}":${value}}`, Blockly.JavaScript.ORDER_ATOMIC];
34+
};
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/* eslint-disable no-underscore-dangle */
2+
import { translate } from '../../../../../common/i18n';
3+
import { expectValue } from '../shared';
4+
5+
Blockly.Blocks.webhook = {
6+
init() {
7+
this.jsonInit({
8+
message0: translate('Webhook URL: %1'),
9+
args0 : [
10+
{
11+
type: 'input_value',
12+
name: 'WEBHOOK_URL',
13+
},
14+
],
15+
colour : '#dedede',
16+
previousStatement: null,
17+
nextStatement : null,
18+
tooltip : translate('Sends a POST request to a URL'),
19+
});
20+
21+
this.itemCount_ = 1;
22+
this.updateShape_(false);
23+
this.setMutator(new Blockly.Mutator(['lists_create_with_item']));
24+
},
25+
/**
26+
* Create XML to represent list inputs.
27+
* @return {!Element} XML storage element.
28+
* @this Blockly.Block
29+
*/
30+
mutationToDom() {
31+
const container = document.createElement('mutation');
32+
container.setAttribute('items', this.itemCount_);
33+
return container;
34+
},
35+
/**
36+
* Parse XML to restore the list inputs.
37+
* @param {!Element} xmlElement XML storage element.
38+
* @this Blockly.Block
39+
*/
40+
domToMutation(xmlElement) {
41+
this.itemCount_ = parseInt(xmlElement.getAttribute('items'));
42+
this.updateShape_(false);
43+
},
44+
/**
45+
* Populate the mutator's dialog with this block's components.
46+
* @param {!Blockly.Workspace} workspace Mutator's workspace.
47+
* @return {!Blockly.Block} Root block in mutator.
48+
* @this Blockly.Block
49+
*/
50+
decompose(workspace) {
51+
const containerBlock = workspace.newBlock('lists_create_with_container');
52+
containerBlock.initSvg();
53+
54+
let { connection } = containerBlock.getInput('STACK');
55+
for (let i = 0; i < this.itemCount_; i++) {
56+
const itemBlock = workspace.newBlock('lists_create_with_item');
57+
itemBlock.initSvg();
58+
connection.connect(itemBlock.previousConnection);
59+
connection = itemBlock.nextConnection;
60+
}
61+
return containerBlock;
62+
},
63+
/**
64+
* Reconfigure this block based on the mutator dialog's components.
65+
* @param {!Blockly.Block} containerBlock Root block in mutator.
66+
* @this Blockly.Block
67+
*/
68+
compose(containerBlock) {
69+
let itemBlock = containerBlock.getInputTargetBlock('STACK');
70+
// Count number of inputs.
71+
const connections = [];
72+
while (itemBlock) {
73+
connections.push(itemBlock.valueConnection_);
74+
itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock();
75+
}
76+
this.itemCount_ = connections.length;
77+
this.updateShape_(true);
78+
},
79+
/**
80+
* Modify this block to have the correct number of inputs.
81+
* @private
82+
* @this Blockly.Block
83+
*/
84+
updateShape_(attachInput) {
85+
if (this.itemCount_ && this.getInput('EMPTY')) {
86+
this.removeInput('EMPTY');
87+
} else if (!this.itemCount_ && !this.getInput('EMPTY')) {
88+
this.appendDummyInput('EMPTY').appendField(translate('Empty payload'));
89+
}
90+
let i;
91+
for (i = 0; i < this.itemCount_; i++) {
92+
if (!this.getInput(`ADD${i}`)) {
93+
const input = this.appendValueInput(`ADD${i}`);
94+
95+
if (i === 0) {
96+
input.appendField(translate('Payload:'));
97+
}
98+
99+
if (!attachInput) {
100+
return;
101+
}
102+
const { connection } = input;
103+
const keypair = this.workspace.newBlock('key_value_pair', `keyvalue${i}`);
104+
keypair.initSvg();
105+
keypair.render();
106+
keypair.outputConnection.connect(connection);
107+
}
108+
}
109+
// Remove deleted inputs.
110+
while (this.getInput(`ADD${i}`)) {
111+
this.removeInput(`ADD${i}`);
112+
i++;
113+
}
114+
},
115+
onchange: function onchange(ev) {
116+
if (!this.workspace || this.isInFlyout || this.workspace.isDragging()) {
117+
return;
118+
}
119+
120+
if (ev.type === Blockly.Events.MOVE) {
121+
for (let i = 0; i < this.itemCount_; i++) {
122+
const currentBlock = this.getInputTargetBlock(`ADD${i}`);
123+
if (currentBlock && currentBlock.type !== 'key_value_pair') {
124+
currentBlock.unplug(true);
125+
}
126+
}
127+
}
128+
},
129+
};
130+
131+
Blockly.JavaScript.webhook = block => {
132+
const url = expectValue(block, 'WEBHOOK_URL');
133+
134+
if (!block.itemCount_) {
135+
return `Bot.sendWebhook(${url}, null);\n`;
136+
}
137+
138+
const keypairs = new Array(block.itemCount_);
139+
for (let i = 0; i < block.itemCount_; i++) {
140+
keypairs[i] = Blockly.JavaScript.valueToCode(block, `ADD${i}`, Blockly.JavaScript.ORDER_ATOMIC) || null;
141+
}
142+
143+
const params = keypairs
144+
.filter(item => item !== null)
145+
.map(item => {
146+
const regExp = /^{(.*?)}$/;
147+
return item && item.match(regExp)[1];
148+
});
149+
150+
return `Bot.sendWebhook(${url}, {${params}});\n`;
151+
};

static/xml/toolbox.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,19 @@
469469
</block>
470470
<block type="loader"></block>
471471
<block type="block_holder"></block>
472+
<block type="webhook">
473+
<value name="WEBHOOK_URL">
474+
<shadow type="text">
475+
<field name="TEXT">https://example.com</field>
476+
</shadow>
477+
</value>
478+
<value name="ADD0">
479+
<block type="key_value_pair">
480+
</block>
481+
</value>
482+
</block>
483+
<block type="key_value_pair">
484+
</block>
472485
</category>
473486
</category>
474487
</category>

0 commit comments

Comments
 (0)